溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Angularjs進(jìn)階筆記(2)-自定義指令中的數(shù)據(jù)綁定

發(fā)布時(shí)間:2020-05-31 12:34:35 來(lái)源:網(wǎng)絡(luò) 閱讀:1024 作者:大史不說(shuō)話 欄目:web開(kāi)發(fā)

Angularjs進(jìn)階筆記(2)-自定義指令中的數(shù)據(jù)綁定

有關(guān)自定義指令的scope參數(shù),網(wǎng)上很多文章都在講這3種綁定方式實(shí)現(xiàn)的效果是什么,但幾乎沒(méi)有人講到底怎么使用,本篇希望聊聊到底怎么用這個(gè)話題。

一. 自定義指令

自定義指令,是Angularjs用來(lái)實(shí)現(xiàn)組件化的方式,相比于ReactVue的組件化方式,它真的很復(fù)雜,自定義指令太重了,它暴露了太多可供定制的參數(shù),以至于普通的開(kāi)發(fā)者完全不知道要用它來(lái)做什么而將其束之高閣,畢竟一般的業(yè)務(wù)邏輯通過(guò)controller和service就已經(jīng)可以完成了。

自定義指令在Angularjs項(xiàng)目中主要有兩大用途:

  • 1.封裝指定組件的DOM操作

    Angularjs期望的開(kāi)發(fā)方式是將DOM的操作盡可能封裝在自定義指令中,這樣對(duì)于局部變量的操作會(huì)更容易加入到Angular自己的生命周期中。

  • 2.組件化

    Angularjs靠自定義指令實(shí)現(xiàn)組件化。諸如你在ReactVue中看到的類似于<Content />,<Sidebar />這樣的自定義標(biāo)簽,或是父級(jí)子級(jí)傳值所使用的prop,又或者是標(biāo)記組件自身狀態(tài)的state,在Angularjs中全部都是通過(guò)自定義指令來(lái)實(shí)現(xiàn)的。

二. 數(shù)據(jù)綁定的形式

自定義指令在定義后,需要在html文件中編寫(xiě),最常用的方式是將其書(shū)寫(xiě)為標(biāo)簽屬性。當(dāng)使用自定義指令時(shí),常常需要將一個(gè)變量的值從controller傳遞至directive中,此時(shí)需要在scope屬性中進(jìn)行變量綁定設(shè)置,Angularjs提供了3種不同的綁定方式(實(shí)際上也可以直接傳遞True),如下所示:

scope: {
   infiniteScroll: '=', // 將infiniteScroll同父級(jí)controller中的指定對(duì)象雙向綁定
   onSend: '&', // 從父級(jí)獲取一個(gè)變量的引用,常用作方法調(diào)用
   fromName: '@' // 從父級(jí)獲取值后便只在本地作用域生效
}

關(guān)于三種綁定方式使用的方法,網(wǎng)上可以搜到非常多的文章,本篇不再贅述,今天我們只來(lái)詳細(xì)看一下這幾種方式的使用場(chǎng)景和區(qū)別。

2.1 @綁定

@綁定可以轉(zhuǎn)移常量賦值的位置,常用于為自定義封裝組件暴露一個(gè)可設(shè)定常量參數(shù)的接口。這種綁定方式的意義,在于從自定義指令外部(一般是從html頁(yè)面上綁定一個(gè)常量或控制器中的變量)獲取一個(gè)局部變量的值。

實(shí)際場(chǎng)景:

例如我們封裝了一個(gè)分頁(yè)組件,其中指令局部作用域中的displayPaginationNums屬性用于決定分頁(yè)組件的頁(yè)碼欄顯示多少個(gè)按鈕,然后把剩余的按鈕收起來(lái)并添加...按鈕,這是一個(gè)很常見(jiàn)的需求。

  • 不使用@綁定

    不使用@綁定,完全可以做到,只需要在link函數(shù)里,初始化為其賦值即可。

  link:function(scope, elements, attrs){
        scope.displayPaginationNums = 5;//用于決定分頁(yè)導(dǎo)航欄最多可顯示幾個(gè)數(shù)字
  },

使用這樣的方式,就可以,但我們默認(rèn)了一個(gè)前提,那就是所有調(diào)用這個(gè)組件的人,都會(huì)瀏覽這個(gè)組件的源代碼。這其實(shí)是很不方便的,換位思考一下,你使用Angularjs的時(shí)候,會(huì)先去源碼里找一下對(duì)應(yīng)的方法開(kāi)頭都定義了哪些變量,哪些可以修改嗎?當(dāng)然不會(huì)。

這個(gè)屬性在不同的項(xiàng)目中都會(huì)需要賦值,但需要?jiǎng)討B(tài)去修改的場(chǎng)景其實(shí)并不多,所以我們需要將接口暴露至更高的開(kāi)發(fā)層級(jí),供調(diào)用者直接賦值。

  • 使用@綁定

    當(dāng)使用@綁定后,我們實(shí)際上是面向調(diào)用者暴露了去設(shè)定重要參數(shù)的接口,使用起來(lái)更加方便。下面的寫(xiě)法讓開(kāi)發(fā)者使用這個(gè)組件時(shí),可以在代碼編寫(xiě)時(shí)方便地傳入自己想要設(shè)定的值:

  //指令定義時(shí)
  scope:{
      displayPaginationNums:'@'
  },
  <!--指令調(diào)用時(shí)-->
  <div table-pagination
       display-pagination-nums="5">

面向?qū)ο蟪绦蛟O(shè)計(jì)原則中有一個(gè)重要的原則,叫做開(kāi)放封閉原則,它的意思是說(shuō),你在程序設(shè)計(jì)中所書(shū)寫(xiě)的代碼,應(yīng)該對(duì)擴(kuò)展開(kāi)放,對(duì)修改封閉。簡(jiǎn)單地說(shuō)就是你所編寫(xiě)的代碼成型以后,在后續(xù)的使用和功能擴(kuò)展的時(shí)候,盡可能不需要再去改動(dòng)代碼,而只需要通過(guò)編寫(xiě)與擴(kuò)展相關(guān)的代碼即可。

此處就是從封閉轉(zhuǎn)為開(kāi)放的一個(gè)示例,雖然看起來(lái)很細(xì)小,但可以很明確地表達(dá)這個(gè)原則。

2.2 &綁定

&綁定用于傳遞父級(jí)函數(shù)的引用,用來(lái)調(diào)用父級(jí)控制器中定義的方法。如果只是以業(yè)務(wù)邏輯為模塊進(jìn)行封裝,這種綁定方式可以幫我們避免一部分代碼重復(fù),如果是為通用框架編寫(xiě)純組件,則可以為調(diào)用者提供自定義函數(shù)的接口。

實(shí)際場(chǎng)景:

比如我們?cè)谥谱饕粋€(gè)表格和分頁(yè)組件時(shí),表格每一頁(yè)只顯示10條數(shù)據(jù),分頁(yè)是后臺(tái)來(lái)完成的,那么每一次點(diǎn)擊分頁(yè)組件上的頁(yè)碼按鈕時(shí),我們都需要向后臺(tái)發(fā)送ajax請(qǐng)求來(lái)獲取新一頁(yè)的數(shù)據(jù)。那么這個(gè)發(fā)送ajax請(qǐng)求的方法你會(huì)寫(xiě)在哪里呢?

不使用&綁定

  • 將方法寫(xiě)在controller中

    優(yōu)勢(shì):這樣做的好處是如果以后我們需要增加一個(gè)輸入框來(lái)實(shí)現(xiàn)精確跳轉(zhuǎn)到哪一頁(yè)時(shí),可以直接在模板中使用ng-change="sendAjax( )"來(lái)綁定這個(gè)方法,方便復(fù)用,擴(kuò)展,甚至修改功能。

    劣勢(shì):但這樣做的話,如果想在自定義指令中就無(wú)法直接調(diào)用這個(gè)方法,常見(jiàn)的處理策略是在自定義指令中使用scope.$emit( )將一個(gè)自定義事件發(fā)送至父級(jí)controller,在父級(jí)controller中使用$scope.$on( )來(lái)監(jiān)聽(tīng)這個(gè)自定義事件,并在回調(diào)中執(zhí)行$scope.sendAjax( )這個(gè)方法。

  • 將方法寫(xiě)在指令的link函數(shù)中

    優(yōu)勢(shì):可以將一些不需要用戶感知的函數(shù)封裝起來(lái),例如數(shù)據(jù)發(fā)送前的校驗(yàn),或是響應(yīng)數(shù)據(jù)的結(jié)構(gòu)重組等,提高業(yè)務(wù)邏輯相關(guān)的代碼在controller中的比重,減小controller的體積。

    劣勢(shì):當(dāng)其他組件想要使用這個(gè)方法時(shí)會(huì)很困難,Angularjs并沒(méi)有提供一種跨directive調(diào)用方法的機(jī)制。

    實(shí)際上在開(kāi)發(fā)過(guò)程中,不熟悉&綁定的開(kāi)發(fā)者在使用自定義指令時(shí),幾乎都會(huì)選擇將方法寫(xiě)在controller中并通過(guò)消息機(jī)制來(lái)觸發(fā)這個(gè)函數(shù)(也就是上文中第一個(gè)方法),他們希望指令所封裝的組件是純粹的,換句話說(shuō),它是可復(fù)用且與業(yè)務(wù)邏輯剝離的。

使用&綁定

  • 對(duì)于業(yè)務(wù)邏輯開(kāi)發(fā)而言

    簡(jiǎn)潔且容易使用,組件可直接調(diào)用controller中的業(yè)務(wù)邏輯代碼,避免了當(dāng)自定義事件過(guò)多時(shí)造成的controller中充滿了事件監(jiān)聽(tīng)的回調(diào)方法的問(wèn)題,使用方法如下:

    //主模板中
    <div change-page="sendAjax"></div>
    //指令定義中
    ...
    template:'<div ng-click="changePage()"></div>'
    scope:{
        changePage: '&'
    },
    ...
  • 對(duì)于模塊封裝而言

    從上面的示例就可以看出,自定義指令中實(shí)際執(zhí)行的changePage( )方法,是用戶在使用這個(gè)組件時(shí)編寫(xiě)在controller之中的sendAjax( )這個(gè)方法,當(dāng)我們需要封裝一個(gè)供其他開(kāi)發(fā)者調(diào)用的組件時(shí)(往往是在編寫(xiě)一個(gè)組件庫(kù)),這種結(jié)構(gòu)是在angular中最自然的實(shí)現(xiàn)方式。

當(dāng)你希望給一個(gè)自定義指令暴露越來(lái)越多個(gè)性化定制接口時(shí),它很可能變得臃腫,甚至一無(wú)是處。

&綁定意義,在于將業(yè)務(wù)邏輯從組件中剝離出來(lái),但過(guò)多的可定制性又會(huì)給開(kāi)發(fā)者帶來(lái)額外的問(wèn)題,你會(huì)發(fā)現(xiàn),僅僅是簡(jiǎn)單地使用一個(gè)下拉框或是勾選框之類的簡(jiǎn)單組件時(shí),就需要傳入一大堆自定屬性,而這本該是在交互設(shè)計(jì)標(biāo)準(zhǔn)中確定好并編寫(xiě)在項(xiàng)目中的指定位置的。自定義指令的可定制性越高,html模板的體積就會(huì)越大,controller中的代碼量也會(huì)隨之增大,帶來(lái)的直接問(wèn)題就是:開(kāi)發(fā)很方便,維護(hù)很痛苦。

2.3 =綁定

=綁定是3中綁定形式中最常用的一種,常用于將用于渲染的數(shù)組或?qū)ο髠魅胱远x指令中。這樣做可以將業(yè)務(wù)邏輯分塊,使得代碼結(jié)構(gòu)更具有層次性,降低維護(hù)難度。

實(shí)際場(chǎng)景:

一個(gè)表格組件,需要通過(guò)ajax請(qǐng)求從后臺(tái)獲取100條用于展示的數(shù)據(jù),這些數(shù)據(jù)可能需要排序,過(guò)濾,分頁(yè)等操作,首先應(yīng)該明確的是,即時(shí)這些代碼全部寫(xiě)在controller中,程序也是可以運(yùn)行的,只是當(dāng)你在其他場(chǎng)合需要復(fù)用時(shí),就需要復(fù)制粘貼很多代碼。那么該如何來(lái)設(shè)計(jì)這樣一個(gè)功能并提取公用組件呢?排序過(guò)濾,分頁(yè)都是表格組件的通用動(dòng)作,也就是說(shuō)與數(shù)據(jù)對(duì)象本身的結(jié)構(gòu)并沒(méi)有太大關(guān)系,對(duì)于一個(gè)通用型表格控件來(lái)說(shuō),我們唯一必須要傳入的只有一項(xiàng)——數(shù)據(jù)源,且它是有可能會(huì)隨著用戶操作而發(fā)生變化的。

推薦的技術(shù)方案為:

  • service : 封裝$http操作,信息提示,及容錯(cuò)處理
  • controller : 調(diào)用service暴露的方法從后臺(tái)獲取數(shù)據(jù),并賦值給指定變量
  • directive : 雙向數(shù)據(jù)綁定controller中的變量以獲取驅(qū)動(dòng)表格渲染的數(shù)據(jù),將排序,過(guò)濾,分頁(yè)的具體實(shí)現(xiàn)封裝在指令內(nèi)部。

這樣的結(jié)構(gòu),使宏觀業(yè)務(wù)邏輯前后臺(tái)信息交互,組件通用功能分別在不同的模塊中實(shí)現(xiàn),可以極大提高定位問(wèn)題的速度。

=綁定的雙向數(shù)據(jù)綁定在使用中是存在一些方法問(wèn)題的,詳情請(qǐng)參考《Angularjs1.X進(jìn)階筆記(1)—兩種不同的雙向數(shù)據(jù)綁定》。

三. 自定義指令的實(shí)用意義

  • =綁定—— 常用于傳遞從后臺(tái)獲取的用于驅(qū)動(dòng)純組件的源數(shù)據(jù)。

  • @綁定—— 為自定義指令中傳遞可配置的常量參數(shù)提供設(shè)置接口。

  • &綁定—— 為自定義指令中傳遞自定義方法提供接口。
向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI