1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        前端代碼的三種設(shè)計(jì)模式

        共 3526字,需瀏覽 8分鐘

         ·

        2022-06-08 23:43

        前端作為軟件工程長(zhǎng)期發(fā)展出來(lái)的一個(gè)獨(dú)立分支,一直沒(méi)有屬于自己的特定的代碼設(shè)計(jì)模式,最近我們?cè)趯?shí)踐中對(duì)一些發(fā)源于面向?qū)ο蟮拇a設(shè)計(jì)做了一些總結(jié),總結(jié)了三種模式,遂有此文予以分享。

        為了便于理解,以下代碼示例采用的都是 React + rdeco 編寫(xiě),設(shè)計(jì)模式本身是高度抽象的,并不局限于某一類(lèi)特定的框架。

        組件模式

        組件模式是我們用的最多的或者說(shuō)目前大家都唯一能夠理解的模式,組件模式的特點(diǎn)是,予以每個(gè)組件獨(dú)立的上下文,組件和組件之間有嚴(yán)格的代碼隔離,通常在不考慮全局變量的影響下組件之間是完全無(wú)潛在交互的。


        const?Table?=?createComponent({
        ??name:'table',
        ??state:{
        ????data:[],
        ??},
        ??view:{
        ????render(){
        ??????return(
        ????????
        {this.state.data.map(d=>{
        ??????????return?d
        ????????})}

        ??????)
        ????}
        ??}
        })

        const?Page?=?createComponent({
        ??name:'page',
        ??view:{
        ????render(){
        ??????return(
        ????????
        ??????)
        ????}
        ??}
        })
        復(fù)制代碼

        這種模式我們都很熟悉,Page 和 Table 是兩個(gè)擁有獨(dú)立上下文的組件,在不同的 UI 框架里有不同的組件交互方式,在 React 中,Page 如果要和 Table 進(jìn)行交互,可以使用 props 傳遞,或者借助 Context 來(lái)共享一部分上下文。

        但是這種模式在很多場(chǎng)景下并不是完全有效的,只有當(dāng)我們非常明確兩個(gè)組件之間的邊界時(shí),模式和實(shí)際情況才是相符合的,例如考慮這樣一種場(chǎng)景

        const?HeadTitle?=?({text})=>{
        ??return(
        ????<p>{text}p>
        ??)
        }
        const?Page?=?createComponent({
        ??name:'page',
        ??state:{
        ????text:'page',
        ??},
        ??view:{
        ????render(){
        ??????this.state.text}>
        ????}
        ??}
        })

        復(fù)制代碼

        在這個(gè)示例中,乍看是沒(méi)啥問(wèn)題,平時(shí)我們都會(huì)將一些無(wú)狀態(tài)的 UI 提取為無(wú)狀態(tài)的函數(shù)組件,但經(jīng)過(guò)實(shí)踐你會(huì)發(fā)現(xiàn)實(shí)際上,HeadTitle 大概率僅服務(wù)于 Page,也就是說(shuō) HeadTitle 并不是為了復(fù)用而被提取,更多是因?yàn)榇笮徒M件的文件需要拆解從而減小體積,降低管理難度。

        但是以此為目的進(jìn)行組件化拆解會(huì)破壞原有組件的完整性,導(dǎo)致大量的參數(shù)傳遞,這和我們過(guò)度提取代碼到函數(shù)其實(shí)是一個(gè)效果。

        function?print(name){
        ??console.log(name)
        }
        function?main(){
        ??const?name?=?'main'
        ??print(name)
        }
        //?如果?print?在?main?函數(shù)內(nèi)部則不需要再次傳遞?name
        function?main(){
        ??const?name?=?'main'
        ??function?print(){
        ????console.log(name)
        ??}
        ??print(name)
        }
        //?因此對(duì)于 main 來(lái)說(shuō) print 是一個(gè)獨(dú)立函數(shù)?,還是一個(gè)代碼片段?
        復(fù)制代碼

        為了解決組件提取導(dǎo)致的上下文隔離問(wèn)題,我們實(shí)踐了一種模式,我們稱(chēng)之為組合模式

        組合模式

        和組件模式相比,組合模式是一種輕量化的方案,相比組件模式兩者有明顯的區(qū)別

        1. 組件模式擁有獨(dú)立的上下文,組件和組件之間組合成新的組件需要進(jìn)行上下文的傳遞,而組合模式則只是組件的一個(gè)片段,若干個(gè)組合體組成了一個(gè)完整組件,組合體之間共享上下文,不需要額外傳遞,但組合體本身實(shí)現(xiàn)了相關(guān)邏輯的內(nèi)聚

        2. 組件和組件之間因?yàn)樯舷挛母綦x,因此可以擁有相同的內(nèi)部成員,組合體只是組件的一個(gè)片段,組合體之間不能用相同的內(nèi)部成員。

        3. 組件有實(shí)例,需要命名標(biāo)識(shí),組合體沒(méi)有實(shí)例,不需要命名標(biāo)識(shí)

        參照以上區(qū)別我們來(lái)看看的代碼示例

        const?table?=?createCompose({
        ??view:{
        ????renderTable(){
        ??????return(
        ????????<div>{this.state.data.map(d=>{
        ??????????return?d
        ????????})}<div>
        ??????)
        ????}
        ??}
        })

        const?head?=?createCompose({
        ??state:{
        ????text:'page'
        ??},
        ??view:{
        ????renderHead(){
        ??????return(
        ????????<p>{text}p>

        ??????)
        ????}
        ??}
        })

        const?Page?=?createComponent(compose({
        ??name:'page',
        ??state:{
        ????data:[]
        ??},
        ??view:{
        ????render(){
        ??????<>
        ????????{this.view.renderHead()}
        ????????{this.view.renderTable()}
        ??????
        ????}
        ??}
        },[table,?head]))


        復(fù)制代碼

        現(xiàn)在 head 和 table 都成了組合體,通過(guò)組合變成了 page 的一部分,為此他們可以共享彼此的上下文,而不用額外通過(guò) props 或者 Context 來(lái)傳遞或者共享參數(shù)

        除了組合模式,我們還總結(jié)了第三種模式,membrane 模式,這種模式我在早期的文章中有提到過(guò),今天我們將其簡(jiǎn)化。

        Membrane 模式

        和組合模式相比,membrane 模式具有一些共通性,例如同樣沒(méi)有獨(dú)立的上下文,不需要命名標(biāo)識(shí),不過(guò)兩者也有極大的區(qū)別

        1. membrane 是一種抽象模式,和組合模式相比,每個(gè) membrane 只能有一個(gè)模板
        2. compose 和 membrane 可以聯(lián)合使用
        const?pageTemplate?=?()?=>?{
        ??return?{
        ????state:{
        ??????name:'',
        ????},
        ????service:{
        ??????init(){}
        ????},
        ????controller:{
        ??????onMount(){
        ????????this.service.init()
        ??????}
        ????},
        ????view:{
        ??????render(){
        ????????return(
        ??????????<div>{this.state.name}div>
        ????????)
        ??????}
        ????}
        ??}
        }

        const?Page1Membrane?=?createMembrane(pageTemplate(),?{
        ??name:'page-1-membrane',
        ??service:{
        ????init(){
        ??????this.setter.name('page-1-membrane')
        ????}
        ??}
        })

        const?Page1Membrane?=?createMembrane(pageTemplate(),?{
        ??name:'page-1-membrane',
        ??service:{
        ????init(){
        ??????this.setter.name('page-2-membrane')
        ????}
        ??}
        })

        const?Page1?=?createComponent(Page1Membrane)
        //?render?Page1?name?===?page-1-membrane

        const?Page2?=?createComponent(Page2Membrane)
        //?render?Page2?name?===?page-2-membrane

        復(fù)制代碼

        如果你熟悉面向?qū)ο笤O(shè)計(jì),那么可能會(huì)很快聯(lián)想到 membrane 和 抽象類(lèi)的特性有些相似,不過(guò)相比抽象類(lèi),membrane 可以包含具體的實(shí)現(xiàn),因此兩者也不完全等價(jià),但是從設(shè)計(jì)上是有一定的共通性的

        在實(shí)際實(shí)踐中,我們結(jié)合上述三種模式,借助類(lèi)似 mermaid 這樣的 UML 圖形庫(kù),在日常迭代中增加了前端設(shè)計(jì)相關(guān)的內(nèi)容,從實(shí)際結(jié)果看我們認(rèn)為這些模式有助于改善前端設(shè)計(jì)的粗糙和非專(zhuān)業(yè)性,同時(shí)可以改善前端代碼的標(biāo)準(zhǔn)化程度,利用 UML 圖更好的代替注釋和文字文檔來(lái)描述業(yè)務(wù)代碼的組成關(guān)系。

        如果你對(duì)此感興趣可以留言評(píng)論,歡迎交流和討論??

        關(guān)于本文

        作者:掘金泥石流

        https://juejin.cn/post/7081147167653494797

        祝 :2022 年暴富!萬(wàn)事如意!

        點(diǎn)贊和在看就是最大的支持,比心??

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

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产无码99 | 富豪的性玩物h | 国产精品成人无码a v毛片 | 夜夜夜夜夜猛噜噜噜噜gg夜 | 超碰午夜在线观看 | 怡红院自拍 | 国模私拍大尺度gogo | 打炮网址| 亚洲AV无码五区六区七区八区 | 久久艹国产视频 |