<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          聊聊前端領(lǐng)域那些“門面”

          共 3555字,需瀏覽 8分鐘

           ·

          2021-07-14 15:00

          門面模式(Facade)是 23 種經(jīng)典設(shè)計(jì)模式之一,也叫外觀模式,是通過在客戶端和子系統(tǒng)之間引入一個(gè)中間層,將內(nèi)部復(fù)雜度隱藏,暴露出一個(gè)簡單易用的接口。

          引入門面模式之后,對客戶端來說,使用起來會(huì)簡單很多,不再需要了解具體的細(xì)節(jié)。

          比如,沒用門面模式之前,可能是這樣的調(diào)用關(guān)系,客戶端需要了解每一個(gè)內(nèi)部細(xì)節(jié)

          而用了門面模式之后,客戶端不再需要了解具體每一個(gè)模塊,只需要把自己的需求告訴 Facade,然后它去調(diào)用內(nèi)部模塊

          加了一個(gè)門面,有改變功能么?并沒有,只是使得對外的接口更易用了。而這,就是門面模式的意義:封裝內(nèi)部細(xì)節(jié),簡化調(diào)用

          其實(shí)在軟件領(lǐng)域這種門面太多了,各種 DSL(領(lǐng)域特定語言) 包括 html、css 還有 vue 的 template、react 的 jsx 都算是門面,babel 和 eslint 的 preset 也是門面。

          下面我們分別來分析一下。

          簡化 dom 創(chuàng)建的門面:html

          瀏覽器提供了 dom api,基于 dom api 我們就可以構(gòu)建 dom 樹,那為什么需要 html 呢?不用 html 可以么?

          比如 dom api 創(chuàng)建 dom:

          const div = document.createElement('div');
          div.className = "a";

          const img = document.createElement('img');
          img.src="./b.jpg"

          div.appendChild(img);

          和 html 描述 dom:

          <div class="a">
              <img src="./b.jpg">
          </div>

          兩者并沒有區(qū)別。

          所以,html 并沒有增加功能,它只是簡化了 dom 操作,這種明顯就是一種門面模式,不過是通過 DSL 的方式。

          DSL 是指領(lǐng)域特定語言,設(shè)計(jì)一種語法來簡化邏輯的描述,然后通過解析該語言來專程描述的目標(biāo)。瀏覽器就是通過解析 html 來構(gòu)建 dom 樹的。

          簡化樣式描述的門面:css

          css 同樣也是一種 dsl,為了簡化樣式信息的描述。

          比如直接給 dom 添加樣式會(huì)比較麻煩:

          const div = document.querySelector('.a');
          div.style.backgroundColor = 'blue';

          const img = div.querySelector('img');
          img.style.border = '2px';

          而通過 css 來添加就簡單很多:

          .a {
              background-color: blue;
          }
          .a img {
              border: 2px;
          }

          css 有增加新功能么?沒有,它只是使得樣式描述更簡單,同樣,css 這種 dsl 也是由瀏覽器來解析的。

          vue 的 template

          我們知道操作視圖基于 dom api 就足夠了,前端框架就是把數(shù)據(jù)映射到視圖,而映射的目標(biāo)也是 dom api(當(dāng)然,中間有了一層虛擬 dom,那么 api 也是先創(chuàng)建虛擬 dom),但是 dsl 就沒必要選擇用 html 了,完全可以用其他的更適合自己特點(diǎn)的方式來描述。

          vue 選擇了 template:

          如果直接用 api 描述視圖,不夠直觀:

          render: function (createElement{
            return createElement('h1'this.blogTitle)
          }

          vue 選擇了 template 的方式,類似 html:

          <h1>{{ blogTitle }}</h1>

          這樣并沒有增加功能,只是讓開發(fā)者使用框架描述視圖的時(shí)候更簡單,而且 vue 還支持過濾器、指令、插值語法等功能。

          但是引入了 template 的 dsl,也就需要編譯了,不像 html 是瀏覽器解析的,這個(gè)自定義 dsl 需要用自己的編譯器來解析,所以 vue 內(nèi)部有一個(gè) template compiler 來把模版轉(zhuǎn)為 render 函數(shù)。

          react 的 jsx

          react 同樣也是要把對視圖的描述映射成真正的 dom(中間有層虛擬 dom),首先會(huì)提供 api 的方式,但是為了簡化使用,會(huì)提供了描述視圖的方式:jsx。

          直接用 api 的方式比較麻煩:

          const title = React.createElement("h1", {className"main"}, "Hello React");

          jsx 的方式就簡單很多:

          const title = (
            <h1>Hello React</h1>
          );

          vue 和 react 選擇了不同的 dsl。我們知道 dsl 是需要編譯成具體的 api 調(diào)用的,vue 是在框架內(nèi)部實(shí)現(xiàn)的,而 react 的 jsx 則是 babel 實(shí)現(xiàn)(因?yàn)槭?js 語法的擴(kuò)充)。

          可以看到不管是 vue 的 template,還是 react 的 jsx 都沒有增加新的功能,增加這樣一層 dsl 只是為了簡化開發(fā)者對視圖的描述,和 html 的設(shè)計(jì)目的一致,都是門面模式的思想。

          babel 的 preset

          babel 是做代碼轉(zhuǎn)換的,把 es next 的語法,轉(zhuǎn)成目標(biāo)環(huán)境支持的 js 語法,具體完成轉(zhuǎn)換的是一個(gè)個(gè)插件。但是如果開發(fā)者直接去指定插件太過麻煩,比如 es2015 就有一系列插件,而 es2016 又有一堆,如果由開發(fā)者去指定,那使用起來太過復(fù)雜。所以 babel 設(shè)計(jì)出了 preset。

          babel6 的 preset 有 preset-es2015、 preset-es2016 等,他們內(nèi)部就是一系列插件。而 babel7 進(jìn)一步簡化成了 preset-env,只要通過 targets 指定目標(biāo)環(huán)境,那么就會(huì)自動(dòng)選出一系列插件來使用。

          preset 有實(shí)現(xiàn)什么新功能么?沒有,最終轉(zhuǎn)換還是由插件來做的。但是 preset 簡化了開發(fā)者使用 babel 的成本,所以這也是一種典型的門面模式。

          總結(jié)

          門面模式是軟件領(lǐng)域特別常見的一種模式,就是當(dāng)暴露給客戶端的子系統(tǒng)特別復(fù)雜的時(shí)候,通過增加一層門面,由他去和具體的子系統(tǒng)打交道,隔離復(fù)雜度,讓軟件的使用變得簡單。通過隔離復(fù)雜度,讓復(fù)雜度得到很好的治理,不然的話可能會(huì)隨著迭代而使用起來越來越復(fù)雜。

          前端領(lǐng)域常見的 html、css、還有 vue 的 tempalte 以及 react 的 jsx 都是 dsl,dsl 的目的就是為了簡化調(diào)用,是門面模式的典型實(shí)現(xiàn)。(template 和 jsx 要由自己做編譯,而 html、css 是瀏覽器做的編譯)。

          此外,babel 和 eslint 等的 preset 也是為了簡化使用成本而引入的,不然用戶就要直接面對各種復(fù)雜的插件配置。

          門面模式并沒有引入新的功能實(shí)現(xiàn),只是為了簡化系統(tǒng)使用成本而引入的一個(gè)入口。如果遇到系統(tǒng)使用特別復(fù)雜的時(shí)候,不妨通過引入一個(gè)門面(封裝成 api 或者 dsl 的形式)來簡化吧。

          往期推薦

          Vite 太快了,煩死了,是時(shí)候該小睡一會(huì)了。


          如何實(shí)現(xiàn)比 setTimeout 快 80 倍的定時(shí)器?


          萬字長文!總結(jié)Vue 性能優(yōu)化方式及原理


          90 行代碼的 webpack,你確定不學(xué)嗎?





          如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我三個(gè)小忙:

          1. 點(diǎn)個(gè)「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點(diǎn)在看,都是耍流氓 -_-)

          2. 歡迎加我微信「huab119」拉你進(jìn)技術(shù)群,長期交流學(xué)習(xí)...

            關(guān)注公眾號(hào)「前端勸退師」,持續(xù)為你推送精選好文,也可以加我為好友,隨時(shí)聊騷。



          點(diǎn)個(gè)在看支持我吧,轉(zhuǎn)發(fā)就更好了


          瀏覽 89
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  男人操女人在线观看 | 肉色欧美久久久久久久免费看 | 精品无码人妻一区二区免费毛豆 | 免费性在线视频 | 好日吊|