我終於知道公司前端爲啥不加班了…

摘要:如何快速、高效地構建前端組件乃至頁面是解放前端生產力的重要標誌,掌握抽象組件和頁面模型,理解前端可視化搭建思路,擺脫固有的開發模式,提升前端開發效率,是每位前端應該瞭解的。

本文分享自華爲雲社區《【雲駐共創】前端可視化框架是怎樣煉成的?》,原文做者:華爲雲EI專家胡琦。html

隨着移動互聯網的迅猛發展和 5G 技術的普及,前端頁面需求量爆炸增加,用戶交互也變得愈來愈複雜,頁面從零開發的成本也水漲船高。如何快速、高效地構建前端組件乃至頁面是解放前端生產力的重要標誌,掌握抽象組件和頁面模型,理解前端可視化搭建思路,擺脫固有的開發模式,提升前端開發效率,是每位前端應該瞭解的。前端

從一個「栗子」提及

在咱們前端開發過程當中可能常常這樣會遇到這樣的場景:ios

(某天,產品經理找到前端。)
    產品經理:簡單開發一個歡迎頁面,就展現下「歡迎訪問」。
    (這沒什麼難度啊,代碼很好寫了,因而前端不假思索就把代碼秀出來。)
    前端:
        ```
        <template>
            <div>
                歡迎訪問
            </div>
        </template>
        ```
    (一天以後,產品經理以爲這個歡迎詞不夠具體,還想加個主語,因而……)
    產品經理:那個歡迎詞簡單改一下,改爲「歡迎訪問咱們的網站」。
    前端:
        ```
        <template>
            <div>
                歡迎訪問咱們的網站
            </div>
        </template>
        ```
     (通過代碼提交、代碼審覈、代碼合併、部署到測試環境、測試驗證、灰度發佈、產品驗證、
     發佈上線等一系列流程,歡迎詞終於更新了……
     又一天後,產品經理以爲歡迎詞沒有展示出咱們的優點,因而加了個形容詞來描述咱們的網站。)
    產品經理:那個歡迎詞仍是不行,改爲「歡迎訪問咱們帥氣的網站」。
    (迫於產品經理手中40米長大刀的威懾,儘管心中盡是問號,前端仍是修改了代碼。)
    前端:
        ```
        <template>
            <div>
                歡迎訪問咱們帥氣的網站
            </div>
        </template>
        ```
     (又又一天後,產品經理想到一個「狂拽酷炫」的形容詞,因而……)
    產品經理:歡迎詞再改下,改爲「歡迎訪問咱們狂拽酷炫的網站」。
    (此時,前端坐不住了,想到了經過讓產品經理本身維護JSON文件,在頁面中獲取JSON中title字段進行渲染顯示)
    前端:
        ```
        <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>
        ```
        (又又又一天後,產品經理有了另外一個想法,此次不是改歡迎詞了。)
        產品經理:我想再加一個選擇框,用來收集用戶信息。
        (此時,一陣風吹過,前端在風中凌亂了……)

固然,既然能想到經過 JSON 去配置,那意味着整個組件、頁面都能配置,只需給到產品經理一個可視化的界面去配置,便可生成 TA 想要的頁面,大大節省了溝通成本、提高了開發效率。這時,可視化框架應運而生。axios

可視化框架的構成和分工

可視化框架是怎樣的?首先咱們先了解一下可視化框架的構成和分工。開發做爲可視化框架的維護者,能夠提供一個可視化的配置平臺;目標受衆,也就是可視化平臺的使用者,如上文例子中的產品經理;使用者經過可視化配置平臺對頁面進行配置,平臺會產出一份配置文件用來描述頁面並上傳到存儲空間;配置文件經過渲染引擎解析最終生成頁面。在這個構成中,做爲開發框架的維護者,咱們只須要關注可視化配置平臺和渲染引擎,固然可視化配置平臺也只是將使用者的輸入轉化爲渲染引擎能解析的配置文件並上傳,是錦上添花的一環,若是還想應用在更復雜的場景,還能夠加上權限管理,好比 A 只能編輯 A 負責的頁面,B 只能編輯 B 複製的頁面,還能夠實現一個工做流的流程編排,好比審覈……框架

可視化框架的核心在於渲染引擎,咱們如何得出這個渲染引擎以及渲染引擎是如何運做並渲染最終的頁面,是咱們所關心的。如何得出渲染引擎就不得不先說說頁面泛化模型。佈局

頁面泛化模型

爲何會有頁面泛化模型?由於咱們不一樣的頁面實際上是經過渲染引擎解析不一樣的配置文件渲染出來的,所以渲染引擎須要泛化的能力。好比頁面 A 是表單填寫,那麼就會要求渲染引擎可以解析表單的配置文件;好比頁面 B 包含卡片式列表,就會要求渲染引擎可以解析列表的配置文件。頁面泛化模型的創建,主要根據開發者自身的經驗和方法創建知足自身業務需求的模型便可。像上文案例中,若是產品經理一直只要求修改歡迎詞,那案例中的那段 title 的渲染引擎就足夠知足需求了。接下來,以華爲雲官網頁面爲例,拋磚引玉講講頁面泛化模型如何創建。測試

從上面截圖中咱們能夠看出這實際上是一個從上到下的結構,能夠理解爲頁面是由一個個樓層構成的,樓層能夠理解爲body下的一個div塊,或者是一個功能塊。好比圖中從上到下是頁頭、banner、引導跳轉樓層、推薦文章、技術領域樓層。固然咱們常常遇到的頁面也不全都是上下結構,還有左右結構。flex

其實,像這樣左右結構的頁面,您能夠理解外層還有一個更大的容器組件包裹,總體造成一個樓層。容器組件只負責樣式,好比上圖中容器組件負責左右佈局,若是您對佈局尚未概念,您可按下F12鍵查看上圖佈局的代碼,您會看到其實左邊兩個模塊是被classname爲edu-index-version-left的div包裹,右邊兩個模塊是被classname爲edu-index-version-right的div包裹,它們依舊是從上到下的樓層。所以,頁面 = 樓層 + 容器組件。網站

再來看看樓層解構,以上圖爲例,圖中主體部分是一個tab功能組件,經過查看頁面源碼,咱們發現兩處紅色框圈出來的文本並無設計在tab功能組件裏,而是單獨成爲文本控件,這是由於這部分是屬於定製化的功能,並非每一個tab功能組件都有的,就抽離出來了遵循單一職責原則,藍色框是一個容器組件。再來看看tab功能組件中的卡片,卡片也是由一個一個的控件組成。所以,樓層=容器組件 +控件。this

可視化框架中的控件和常見的 UI 框架中的組件同樣,都具備完善且單一的職責,好比表格組件,不管再怎麼加功能都是在表格內部,表格裏面的功能是沒法拆分出去的。但可視化框架中的控件和 UI 框架中的組件仍是有區別的,主要不一樣點在於控件須要用來被編輯,所以它具備統一的props,全部的控件要遵循同樣的props,如視圖配置和數據源,在可視化中咱們不知道頁面會用到哪些組件,所以須要統一去作循環渲染,不感知控件的具體屬性。

可視化框架中的容器組件本質上也是組件,主要負責佈局,分爲基礎容器組件和功能容器組件。基礎容器組件中左右佈局通常經過柵格或者 Flex 實現,上下佈局經過正常的文本流或者定位以及控件自身間距等實現。功能容器組件如 tab 容器、輪播組件等。

當考慮用戶交互時,事件在可視化模型中就不得不考慮。可視化模型中的事件須要關注交互的發起者、交互的做用者以及交互的影響方式,而不須要關注交互的種類和交互的具體內容。好比點擊了某個按鈕,步進器的最大最小值從 一、2 變成 三、4,實際上是改變了input控件的min和max屬性;好比表格篩選加了必定條件以後,顯示數據變少了,是由於觸發了數據事件影響了表格的數據源;好比一個開關組件,點擊以後控制控件的顯示和隱藏……

最終,咱們肯定的可視化模型就是上圖中總結的點。可視化頁面由控件 + 容器組件 + 事件組成,控件的粒度最小,是功能的最小單位;容器組件負責佈局,是樣式的集合;事件響應用戶交互傳遞控件間依賴關係。那控件、容器組件、事件是怎麼結合的呢?就不得不談談渲染引擎了。

渲染引擎

渲染引擎本質上也是組件,主要功能是渲染當層組件、處理當層組件交互關係、對當層組件狀態進行管理。它不關注子層組件,子層組件由子層容器的渲染引擎渲染,由於每一層組件的配置和數據源不同,所以渲染結果也不相同。視圖部分示例代碼(基於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包裹,使用自定義動態組件component的方式定義渲染引擎,帶下劃線的屬性意味着是自定義組件的內置屬性,is決定組件渲染的類型,如button,作到能夠不感知當層組件具體內容渲染當層組件;v-for循環當前組件的屬性;v-show控制組件是否顯示,經過showState進行狀態管理;ref創建索引,能夠用來作一些高級功能,好比父層容器調用子層容器的方法;viewConfig和dataSource就是上文中提到的控件中所必需的;@valueChange是組件提交的統一事件。

父層容器和子層容器本質都是渲染引擎,只是樣式不一樣。好比說一個左右佈局的容器組件,至關於在視圖中v-for循環的地方綁定一個class如柵格佈局或者flex佈局的樣式,若是是柵格佈局的話,用戶就要先定義type是柵格組件,而後配置viewConfig中grid屬性之類的,若是是flex佈局,定義的type就是flex組件,對齊方式如指定爲space-between之類的。上文中示例代碼就是一個正常的從上到下的佈局。

首先外層傳遞兩個關鍵的參數--viewConfig和dataSource,當層容器就會進行配置解析和配置分發。配置解析主要包含屬性映射和生成事件,屬性映射好比控件自己須要title屬性,而配置文件中多是叫label屬性,這時咱們要將label轉換成title,只不過轉換邏輯不包含在渲染引擎中,只是調用外部封裝好的方法;生成事件則是根據配置生成預設事件並掛載。在配置分發以前,會先將解析好的配置進行初始化父層狀態並存放在父層,主要考慮到viewConfig和dataSource不是同步賦值,須要等待都就緒了才進行分發。

在介紹控件的時候,提到每一個控件都要提交,由於每一個控件都不能成爲其餘控件的一個origin。好比Tip組件,雖然自己可能沒有交互,但可能成爲別的控件的依賴項,子層可能須要獲取內容,子層容器的提交會被收集在父層容器的valueWatch中,在子層容器提交之後,若是狀態變化的話,那父層容器就會根據functionList去循環執行的事件;若是是展現類事件,就會更新父層的showState控制顯示或隱藏,若是是數據類事件,則會改變viewConfig和dataSource,對目標進行一個從新賦值。 總得來講渲染引擎流程就包含以上四個步驟:配置解析、配置分發、收集提交、發起事件。

總結

爲了減小頁面開發代碼量,提高代碼複用度,咱們指望頁面能進行可視化編輯;爲了得出一個經過的可視化框架,咱們對頁面進行了可視化建模分析,得出幾乎全部的頁面均可以由控件和容器組件構成,經過泛化的事件處理用戶交互和組件間的級聯關係;根據建模的結果創建了渲染引擎,支撐起整個流程,最終實現可視化。

本文整理自華爲雲社區內容共創活動第二期之【線上直播】2.0倍起步?高效完成前端頁面

查看活動詳情:

 

點擊關注,第一時間瞭解華爲雲新鮮技術~

相關文章
相關標籤/搜索