<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>

          前端可視化框架是怎樣煉成的?

          共 5944字,需瀏覽 12分鐘

           ·

          2021-03-28 10:28

          隨著移動(dòng)互聯(lián)網(wǎng)的迅猛發(fā)展和 5G 技術(shù)的普及,前端頁面需求量爆炸增長(zhǎng),用戶交互也變得越來越復(fù)雜,頁面從零開發(fā)的成本也水漲船高。如何快速、高效地構(gòu)建前端組件乃至頁面是解放前端生產(chǎn)力的重要標(biāo)志,掌握抽象組件和頁面模型,理解前端可視化搭建思路,擺脫固有的開發(fā)模式,提高前端開發(fā)效率,是每位前端應(yīng)該了解的。

          從一個(gè)“栗子”說起

          ? ? ? ? 在我們前端開發(fā)過程中可能經(jīng)常這樣會(huì)遇到這樣的場(chǎng)景:

              (某天,產(chǎn)品經(jīng)理找到前端。)    產(chǎn)品經(jīng)理:簡(jiǎn)單開發(fā)一個(gè)歡迎頁面,就展示下“歡迎訪問”。    (這沒什么難度啊,代碼很好寫了,于是前端不假思索就把代碼秀出來。)    前端:        ```        <template>            <div>                歡迎訪問            </div>        </template>        ```    (一天之后,產(chǎn)品經(jīng)理覺得這個(gè)歡迎詞不夠具體,還想加個(gè)主語,于是……)    產(chǎn)品經(jīng)理:那個(gè)歡迎詞簡(jiǎn)單改一下,改成“歡迎訪問我們的網(wǎng)站”。    前端:        ```        <template>            <div>                歡迎訪問我們的網(wǎng)站            </div>        </template>        ```     (經(jīng)過代碼提交、代碼審核、代碼合并、部署到測(cè)試環(huán)境、測(cè)試驗(yàn)證、灰度發(fā)布、產(chǎn)品驗(yàn)證、     發(fā)布上線等一系列流程,歡迎詞終于更新了……     又一天后,產(chǎn)品經(jīng)理覺得歡迎詞沒有展現(xiàn)出我們的優(yōu)勢(shì),于是加了個(gè)形容詞來描述我們的網(wǎng)站。)    產(chǎn)品經(jīng)理:那個(gè)歡迎詞還是不行,改成“歡迎訪問我們帥氣的網(wǎng)站”。    (迫于產(chǎn)品經(jīng)理手中40米長(zhǎng)大刀的威懾,盡管心中滿是問號(hào),前端還是修改了代碼。)    前端:        ```        <template>            <div>                歡迎訪問我們帥氣的網(wǎng)站            </div>        </template>        ```     (又又一天后,產(chǎn)品經(jīng)理想到一個(gè)“狂拽酷炫”的形容詞,于是……)    產(chǎn)品經(jīng)理:歡迎詞再改下,改成“歡迎訪問我們狂拽酷炫的網(wǎng)站”。    (此時(shí),前端坐不住了,想到了通過讓產(chǎn)品經(jīng)理自己維護(hù)JSON文件,在頁面中獲取JSON中title字段進(jìn)行渲染顯示)    前端:        ```        <template>        <div>            {{title}}        </div>        </template>        <script>        import axios from "axios";        export default {            data() {                return {                    title: ''                }            },            created() {                this.queryTitle()            },            methods: {                queryTitle() {                    axios.get('JSON文件所在路徑').then(res=>{                        if(res && res.status === 200) {                            this.title = res.data.title                        }                    })                }            }        }</script>        ```        (又又又一天后,產(chǎn)品經(jīng)理有了另一個(gè)想法,這次不是改歡迎詞了。)        產(chǎn)品經(jīng)理:我想再加一個(gè)選擇框,用來收集用戶信息。        (此時(shí),一陣風(fēng)吹過,前端在風(fēng)中凌亂了……)


          ? ? ? ? 當(dāng)然,既然能想到通過 JSON 去配置,那意味著整個(gè)組件、頁面都能配置,只需給到產(chǎn)品經(jīng)理一個(gè)可視化的界面去配置,即可生成 TA 想要的頁面,大大節(jié)省了溝通成本、提升了開發(fā)效率。這時(shí),可視化框架應(yīng)運(yùn)而生。

          可視化框架的構(gòu)成和分工

          23672991d6493b91dd24df777449df7d.webp

          ? ? ? ? 可視化框架是怎樣的?首先我們先了解一下可視化框架的構(gòu)成和分工。開發(fā)作為可視化框架的維護(hù)者,可以提供一個(gè)可視化的配置平臺(tái);目標(biāo)受眾,也就是可視化平臺(tái)的使用者,如上文例子中的產(chǎn)品經(jīng)理;使用者通過可視化配置平臺(tái)對(duì)頁面進(jìn)行配置,平臺(tái)會(huì)產(chǎn)出一份配置文件用來描述頁面并上傳到存儲(chǔ)空間;配置文件通過渲染引擎解析最終生成頁面。在這個(gè)構(gòu)成中,作為開發(fā)框架的維護(hù)者,我們只需要關(guān)注可視化配置平臺(tái)和渲染引擎,當(dāng)然可視化配置平臺(tái)也只是將使用者的輸入轉(zhuǎn)化為渲染引擎能解析的配置文件并上傳,是錦上添花的一環(huán),如果還想應(yīng)用在更復(fù)雜的場(chǎng)景,還可以加上權(quán)限管理,比如 A 只能編輯 A 負(fù)責(zé)的頁面,B 只能編輯 B 復(fù)制的頁面,還可以實(shí)現(xiàn)一個(gè)工作流的流程編排,比如審核……
          ? ? ? ? 可視化框架的核心在于渲染引擎,我們?nèi)绾蔚贸鲞@個(gè)渲染引擎以及渲染引擎是如何運(yùn)作并渲染最終的頁面,是我們所關(guān)心的。如何得出渲染引擎就不得不先說說頁面泛化模型。

          頁面泛化模型

          0fa78c7ffe9d0fdf8052b04533a17d4f.webp

          ? ? ? ?為什么會(huì)有頁面泛化模型?因?yàn)槲覀儾煌捻撁嫫鋵?shí)是通過渲染引擎解析不同的配置文件渲染出來的,因此渲染引擎需要泛化的能力。比如頁面 A 是表單填寫,那么就會(huì)要求渲染引擎能夠解析表單的配置文件;比如頁面 B 包含卡片式列表,就會(huì)要求渲染引擎能夠解析列表的配置文件。頁面泛化模型的建立,主要根據(jù)開發(fā)者自身的經(jīng)驗(yàn)和方法建立滿足自身業(yè)務(wù)需求的模型即可。像上文案例中,如果產(chǎn)品經(jīng)理一直只要求修改歡迎詞,那案例中的那段 title 的渲染引擎就足夠滿足需求了。接下來,以華為云官網(wǎng)頁面為例,拋磚引玉講講頁面泛化模型如何建立。

          12f680072d41f62df09441791676d580.webp

          ? ? ? ? 從上面截圖中我們可以看出這其實(shí)是一個(gè)從上到下的結(jié)構(gòu),可以理解為頁面是由一個(gè)個(gè)樓層構(gòu)成的,樓層可以理解為body下的一個(gè)div塊,或者是一個(gè)功能塊。比如圖中從上到下是頁頭、banner、引導(dǎo)跳轉(zhuǎn)樓層、推薦文章、技術(shù)領(lǐng)域樓層。當(dāng)然我們經(jīng)常遇到的頁面也不全都是上下結(jié)構(gòu),還有左右結(jié)構(gòu)。

          efc66639fe54ba3476adbff8d3c4bf6f.webp

          ? ? ? ? 其實(shí),像這樣左右結(jié)構(gòu)的頁面,您可以理解外層還有一個(gè)更大的容器組件包裹,整體形成一個(gè)樓層。容器組件只負(fù)責(zé)樣式,比如上圖中容器組件負(fù)責(zé)左右布局,如果您對(duì)布局還沒有概念,您可按下F12鍵查看上圖布局的代碼,您會(huì)看到其實(shí)左邊兩個(gè)模塊是被classnameedu-index-version-leftdiv包裹,右邊兩個(gè)模塊是被classnameedu-index-version-rightdiv包裹,它們依舊是從上到下的樓層。因此,頁面 = 樓層 + 容器組件

          16593d62fdcfef3bc84ec9eb1b8b308f.webp

          ? ? ? ? 再來看看樓層解構(gòu),以上圖為例,圖中主體部分是一個(gè)tab功能組件,通過查看頁面源碼,我們發(fā)現(xiàn)兩處紅色框圈出來的文本并沒有設(shè)計(jì)在tab功能組件里,而是單獨(dú)成為文本控件,這是因?yàn)檫@部分是屬于定制化的功能,并不是每個(gè)tab功能組件都有的,就抽離出來了遵循單一職責(zé)原則,藍(lán)色框是一個(gè)容器組件。再來看看tab功能組件中的卡片,卡片也是由一個(gè)一個(gè)的控件組成。因此,樓層=容器組件 +控件

          1ef978970c4bf15bdf4b99b056d1e75a.webp

          可視化框架中的控件和常見的 UI 框架中的組件一樣,都具有完善且單一的職責(zé),比如表格組件,無論再怎么加功能都是在表格內(nèi)部,表格里面的功能是無法拆分出去的。但可視化框架中的控件和 UI 框架中的組件還是有區(qū)別的,主要不同點(diǎn)在于控件需要用來被編輯,因此它具有統(tǒng)一的props,所有的控件要遵循一樣的props,如視圖配置和數(shù)據(jù)源,在可視化中我們不知道頁面會(huì)用到哪些組件,因此需要統(tǒng)一去做循環(huán)渲染,不感知控件的具體屬性。

          5be6a07cf22741db4a71b1f5d390161c.webp

          ? ? ? ? 可視化框架中的容器組件本質(zhì)上也是組件,主要負(fù)責(zé)布局,分為基礎(chǔ)容器組件和功能容器組件。基礎(chǔ)容器組件中左右布局一般通過柵格或者 Flex 實(shí)現(xiàn),上下布局通過正常的文本流或者定位以及控件自身間距等實(shí)現(xiàn)。功能容器組件如 tab 容器、輪播組件等。

          96287b229b27ccb154ca5a2d3aa2d1e5.webp

          ? ? ? ? 當(dāng)考慮用戶交互時(shí),事件在可視化模型中就不得不考慮。可視化模型中的事件需要關(guān)注交互的發(fā)起者、交互的作用者以及交互的影響方式,而不需要關(guān)注交互的種類和交互的具體內(nèi)容。比如點(diǎn)擊了某個(gè)按鈕,步進(jìn)器的最大最小值從 1、2 變成 3、4,其實(shí)是改變了input控件的minmax屬性;比如表格篩選加了一定條件之后,顯示數(shù)據(jù)變少了,是因?yàn)橛|發(fā)了數(shù)據(jù)事件影響了表格的數(shù)據(jù)源;比如一個(gè)開關(guān)組件,點(diǎn)擊之后控制控件的顯示和隱藏……

          4cebe14b187df55aed504c77aa823dd8.webp

          ? ? ? ? 最終,我們確定的可視化模型就是上圖中總結(jié)的點(diǎn)。可視化頁面由控件 + 容器組件 + 事件組成,控件的粒度最小,是功能的最小單位;容器組件負(fù)責(zé)布局,是樣式的集合;事件響應(yīng)用戶交互傳遞控件間依賴關(guān)系。那控件、容器組件、事件是怎么結(jié)合的呢?就不得不談?wù)勪秩疽媪恕?/p>渲染引擎

          ? ? ? ? 渲染引擎本質(zhì)上也是組件,主要功能是渲染當(dāng)層組件、處理當(dāng)層組件交互關(guān)系、對(duì)當(dāng)層組件狀態(tài)進(jìn)行管理。它不關(guān)注子層組件,子層組件由子層容器的渲染引擎渲染,因?yàn)槊恳粚咏M件的配置和數(shù)據(jù)源不一樣,因此渲染結(jié)果也不相同。視圖部分示例代碼(基于Vue.js)如下:

          <template>    <div :class="clsPrefix">        <component            :is="component._type"            v-for="component in viewConfig.components"            v-show="showState[component._id]"            :ref="component._id"            :key="component._id"            :viewConfig="component"            :dataSource="dataSource[component._id]"            @valueChange="valueChangeHandler($event, component._id)"        />    </div></template>


          ? ? ? ? 最外層是由div包裹,使用自定義動(dòng)態(tài)組件component的方式定義渲染引擎,帶下劃線的屬性意味著是自定義組件的內(nèi)置屬性,is決定組件渲染的類型,如button,做到可以不感知當(dāng)層組件具體內(nèi)容渲染當(dāng)層組件;v-for循環(huán)當(dāng)前組件的屬性;v-show控制組件是否顯示,通過showState進(jìn)行狀態(tài)管理;ref建立索引,可以用來做一些高級(jí)功能,比如父層容器調(diào)用子層容器的方法;viewConfigdataSource就是上文中提到的控件中所必需的;@valueChange是組件提交的統(tǒng)一事件。

          17ff76d5e80fd085fda5262bbba5efeb.webp

          ? ? ? ? 父層容器和子層容器本質(zhì)都是渲染引擎,只是樣式不同。比如說一個(gè)左右布局的容器組件,相當(dāng)于在視圖中v-for循環(huán)的地方綁定一個(gè)class如柵格布局或者flex布局的樣式,如果是柵格布局的話,用戶就要先定義type是柵格組件,然后配置viewConfiggrid屬性之類的,如果是flex布局,定義的type就是flex組件,對(duì)齊方式如指定為space-between之類的。上文中示例代碼就是一個(gè)正常的從上到下的布局。

          25baac80e93771efa8f1d1d77e89977d.webp

          ? ? ? ? 首先外層傳遞兩個(gè)關(guān)鍵的參數(shù)--viewConfigdataSource,當(dāng)層容器就會(huì)進(jìn)行配置解析和配置分發(fā)。配置解析主要包含屬性映射和生成事件,屬性映射比如控件本身需要title屬性,而配置文件中可能是叫label屬性,這時(shí)我們要將label轉(zhuǎn)換成title,只不過轉(zhuǎn)換邏輯不包含在渲染引擎中,只是調(diào)用外部封裝好的方法;生成事件則是根據(jù)配置生成預(yù)設(shè)事件并掛載。在配置分發(fā)之前,會(huì)先將解析好的配置進(jìn)行初始化父層狀態(tài)并存放在父層,主要考慮到viewConfig和dataSource不是同步賦值,需要等待都就緒了才進(jìn)行分發(fā)。

          b13206fc2aedf6db5c2495cbe6d44d6b.webp

          ? ? ? ? 在介紹控件的時(shí)候,提到每個(gè)控件都要提交,因?yàn)槊總€(gè)控件都不能成為其他控件的一個(gè)origin。比如Tip組件,雖然本身可能沒有交互,但可能成為別的控件的依賴項(xiàng),子層可能需要獲取內(nèi)容,子層容器的提交會(huì)被收集在父層容器的valueWatch中,在子層容器提交以后,如果狀態(tài)變化的話,那父層容器就會(huì)根據(jù)functionList去循環(huán)執(zhí)行的事件;如果是展示類事件,就會(huì)更新父層的showState控制顯示或隱藏,如果是數(shù)據(jù)類事件,則會(huì)改變viewConfigdataSource,對(duì)目標(biāo)進(jìn)行一個(gè)重新賦值。總得來說渲染引擎流程就包含以上四個(gè)步驟:配置解析、配置分發(fā)、收集提交、發(fā)起事件。

          總結(jié)

          ? ? ? ? 為了減少頁面開發(fā)代碼量,提升代碼復(fù)用度,我們期望頁面能進(jìn)行可視化編輯;為了得出一個(gè)通過的可視化框架,我們對(duì)頁面進(jìn)行了可視化建模分析,得出幾乎所有的頁面都可以由控件和容器組件構(gòu)成,通過泛化的事件處理用戶交互和組件間的級(jí)聯(lián)關(guān)系;根據(jù)建模的結(jié)果建立了渲染引擎,支撐起整個(gè)流程,最終實(shí)現(xiàn)可視化。


          本文整理自華為云社區(qū)內(nèi)容共創(chuàng)活動(dòng)第二期之【線上直播】2.0倍起步?高效完成前端頁面。
          查看活動(dòng)詳情:https://bbs.huaweicloud.com/forum/thread-111494-1-1.html


          瀏覽 103
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  免费黄色一级视频 | www.91爱爱 | 在线aⅴ亚洲中文字幕 | 红色一级A片 | 做爱视频网站免费看 |