詳解Angularjs 自定義指令中的數(shù)據(jù)綁定
有關(guān)自定義指令的scope參數(shù),網(wǎng)上很多文章都在講這3種綁定方式實現(xiàn)的效果是什么,但幾乎沒有人講到底怎么使用,本篇希望聊聊 到底怎么用 這個話題。
一. 自定義指令
自定義指令,是 Angularjs
用來實現(xiàn)組件化的方式,相比于 React
和 Vue
的組件化方式,它真的很復雜,自定義指令太重了,它暴露了太多可供定制的參數(shù),以至于普通的開發(fā)者完全不知道要用它來做什么而將其束之高閣,畢竟一般的業(yè)務(wù)邏輯通過controller和service就已經(jīng)可以完成了。
自定義指令在 Angularjs 項目中主要有兩大用途:
1.封裝指定組件的DOM操作
Angularjs 期望的開發(fā)方式是將DOM的操作盡可能封裝在自定義指令中,這樣對于局部變量的操作會更容易加入到Angular自己的生命周期中。
2.組件化
Angularjs 靠自定義指令實現(xiàn)組件化。諸如你在 React 和 Vue 中看到的類似于 , 這樣的自定義標簽,或是父級子級傳值所使用的 prop ,又或者是標記組件自身狀態(tài)的 state ,在 Angularjs 中全部都是通過自定義指令來實現(xiàn)的。
二. 數(shù)據(jù)綁定的形式
自定義指令在定義后,需要在html文件中編寫,最常用的方式是將其書寫為 標簽屬性。 當使用自定義指令時,常常需要將一個變量的值從controller傳遞至directive中,此時需要在 scope
屬性中進行變量綁定設(shè)置, Angularjs 提供了3種不同的綁定方式(實際上也可以直接傳遞True),如下所示:
scope: { infiniteScroll: '=', // 將infiniteScroll同父級controller中的指定對象雙向綁定 onSend: '&', // 從父級獲取一個變量的引用,常用作方法調(diào)用 fromName: '@' // 從父級獲取值后便只在本地作用域生效 }
關(guān)于三種綁定方式使用的方法,網(wǎng)上可以搜到非常多的文章,本篇不再贅述,今天我們只來詳細看一下這幾種方式的使用場景和區(qū)別。
2.1 @綁定
@綁定
可以轉(zhuǎn)移常量賦值的位置,常用于為自定義封裝組件暴露一個可設(shè)定常量參數(shù)的接口。 這種綁定方式的意義,在于從自定義指令外部(一般是從html頁面上綁定一個常量或控制器中的變量)獲取一個局部變量的值。
實際場景:
例如我們封裝了一個分頁組件,其中指令局部作用域中的 displayPaginationNums
屬性用于決定分頁組件的頁碼欄顯示多少個按鈕,然后把剩余的按鈕收起來并添加 ...
按鈕,這是一個很常見的需求。
不使用@綁定
不使用@綁定,完全可以做到,只需要在link函數(shù)里,初始化為其賦值即可。
link:function(scope, elements, attrs){ scope.displayPaginationNums = 5;//用于決定分頁導航欄最多可顯示幾個數(shù)字 },
使用這樣的方式,就可以,但我們默認了一個前提,那就是 所有調(diào)用這個組件的人,都會瀏覽這個組件的源代碼 。這其實是很不方便的,換位思考一下,你使用 Angularjs 的時候,會先去源碼里找一下對應(yīng)的方法開頭都定義了哪些變量,哪些可以修改嗎?當然不會。
這個屬性在不同的項目中都會需要賦值,但需要動態(tài)去修改的場景其實并不多,所以我們需要將接口暴露至更高的開發(fā)層級,供調(diào)用者直接賦值。
使用@綁定
當使用@綁定后,我們實際上是面向調(diào)用者暴露了去設(shè)定重要參數(shù)的接口,使用起來更加方便。下面的寫法讓開發(fā)者使用這個組件時,可以在代碼編寫時方便地傳入自己想要設(shè)定的值:
//指令定義時 scope:{ displayPaginationNums:'@' },
<!--指令調(diào)用時--> <div table-pagination display-pagination-nums="5">
面向?qū)ο蟪绦蛟O(shè)計原則中有一個重要的原則,叫做 開放封閉原則 ,它的意思是說,你在程序設(shè)計中所書寫的代碼, 應(yīng)該對擴展開放,對修改封閉 。簡單地說就是你所編寫的代碼成型以后,在后續(xù)的使用和功能擴展的時候,盡可能不需要再去改動代碼,而只需要通過 編寫與擴展相關(guān)的代碼 即可。
此處就是 從封閉轉(zhuǎn)為開放 的一個示例,雖然看起來很細小,但可以很明確地表達這個原則。
2.2 &綁定
&綁定
用于傳遞父級函數(shù)的引用,用來調(diào)用父級控制器中定義的方法。 如果只是以業(yè)務(wù)邏輯為模塊進行封裝,這種綁定方式可以幫我們避免一部分代碼重復,如果是為通用框架編寫純組件,則可以為調(diào)用者提供自定義函數(shù)的接口。
實際場景:
比如我們在制作一個表格和分頁組件時,表格每一頁只顯示10條數(shù)據(jù),分頁是后臺來完成的,那么每一次點擊分頁組件上的頁碼按鈕時,我們都需要向后臺發(fā)送ajax請求來獲取新一頁的數(shù)據(jù)。那么這個發(fā)送ajax請求的方法你會寫在哪里呢?
不使用&綁定
將方法寫在controller中
優(yōu)勢:這樣做的好處是如果以后我們需要增加一個輸入框來實現(xiàn)精確跳轉(zhuǎn)到哪一頁時,可以直接在模板中使用 ng-change="sendAjax( )"
來綁定這個方法,方便復用,擴展,甚至修改功能。
劣勢:但這樣做的話,如果想在自定義指令中就無法直接調(diào)用這個方法,常見的處理策略是在自定義指令中使用 scope.$emit( )
將一個自定義事件發(fā)送至父級controller,在父級controller中使用 $scope.$on( )
來監(jiān)聽這個自定義事件,并在回調(diào)中執(zhí)行 $scope.sendAjax( )
這個方法。
將方法寫在指令的link函數(shù)中
優(yōu)勢:可以將一些不需要用戶感知的函數(shù)封裝起來,例如數(shù)據(jù)發(fā)送前的校驗,或是響應(yīng)數(shù)據(jù)的結(jié)構(gòu)重組等,提高業(yè)務(wù)邏輯相關(guān)的代碼在controller中的比重,減小controller的體積。
劣勢:當其他組件想要使用這個方法時會很困難,Angularjs并沒有提供一種跨directive調(diào)用方法的機制。
實際上在開發(fā)過程中,不熟悉 &綁定
的開發(fā)者在使用自定義指令時,幾乎都會選擇將方法寫在controller中并通過消息機制來觸發(fā)這個函數(shù)(也就是上文中第一個方法),他們希望指令所封裝的組件是純粹的,換句話說,它是可復用且與業(yè)務(wù)邏輯剝離的。
使用&綁定
對于業(yè)務(wù)邏輯開發(fā)而言
簡潔且容易使用,組件可直接調(diào)用controller中的業(yè)務(wù)邏輯代碼,避免了當自定義事件過多時造成的controller中充滿了事件監(jiān)聽的回調(diào)方法的問題,使用方法如下:
//主模板中 <div change-page="sendAjax"></div>
//指令定義中 ... template:'<div ng-click="changePage()"></div>' scope:{ changePage: '&' }, ...
對于模塊封裝而言
從上面的示例就可以看出,自定義指令中實際執(zhí)行的 changePage( )
方法,是用戶在使用這個組件時編寫在controller之中的 sendAjax( ) 這個方法,當我們需要封裝一個供其他開發(fā)者調(diào)用的組件時(往往是在編寫一個組件庫),這種結(jié)構(gòu)是在angular中最自然的實現(xiàn)方式。
當你希望給一個自定義指令暴露越來越多個性化定制接口時,它很可能變得臃腫,甚至一無是處。
&綁定
意義,在于將業(yè)務(wù)邏輯從組件中剝離出來,但過多的 可定制性 又會給開發(fā)者帶來額外的問題,你會發(fā)現(xiàn),僅僅是簡單地使用一個下拉框或是勾選框之類的簡單組件時,就需要傳入一大堆自定屬性,而這本該是在 交互設(shè)計標準 中確定好并編寫在項目中的指定位置的。自定義指令的可定制性越高,html模板的體積就會越大,controller中的代碼量也會隨之增大,帶來的直接問題就是: 開發(fā)很方便,維護很痛苦。
2.3 =綁定
=綁定
是3中綁定形式中最常用的一種,常用于將用于渲染的數(shù)組或?qū)ο髠魅胱远x指令中 。這樣做可以將業(yè)務(wù)邏輯分塊,使得代碼結(jié)構(gòu)更具有層次性,降低維護難度。
實際場景:
一個表格組件,需要通過ajax請求從后臺獲取100條用于展示的數(shù)據(jù),這些數(shù)據(jù) 可能需要排序,過濾,分頁 等操作,首先應(yīng)該明確的是,即時這些代碼全部寫在controller中,程序也是可以運行的,只是當你在其他場合需要復用時,就需要 復制粘貼 很多代碼。那么該如何來設(shè)計這樣一個功能并提取公用組件呢? 排序 , 過濾 , 分頁 都是表格組件的通用動作,也就是說與數(shù)據(jù)對象本身的結(jié)構(gòu)并沒有太大關(guān)系,對于一個通用型表格控件來說,我們唯一必須要傳入的只有一項—— 數(shù)據(jù)源 ,且它是有可能會隨著用戶操作而 發(fā)生變化 的。
推薦的技術(shù)方案為:
- service : 封裝$http操作,信息提示,及容錯處理
- controller : 調(diào)用service暴露的方法從后臺獲取數(shù)據(jù),并賦值給指定變量
- directive : 雙向數(shù)據(jù)綁定controller中的變量以獲取驅(qū)動表格渲染的數(shù)據(jù),將排序,過濾,分頁的具體實現(xiàn)封裝在指令內(nèi)部。
這樣的結(jié)構(gòu),使 宏觀業(yè)務(wù)邏輯 , 前后臺信息交互 , 組件通用功能 分別在不同的模塊中實現(xiàn),可以極大提高定位問題的速度。
=綁定
的雙向數(shù)據(jù)綁定在使用中是存在一些方法問題的,詳情請參考 《Angularjs1.X進階筆記(1)—兩種不同的雙向數(shù)據(jù)綁定》
。
三. 自定義指令的實用意義
=綁定 —— 常用于傳遞從后臺獲取的用于驅(qū)動純組件的源數(shù)據(jù)。
@綁定 —— 為自定義指令中傳遞可配置的常量參數(shù)提供設(shè)置接口。
&綁定 —— 為自定義指令中傳遞自定義方法提供接口。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- Angularjs之ngModel中的值驗證綁定方法
- 解決angular2在雙向數(shù)據(jù)綁定時[(ngModel)]無法使用的問題
- Angular動態(tài)綁定樣式及改變UI框架樣式的方法小結(jié)
- AngularJS中ng-options實現(xiàn)下拉列表的數(shù)據(jù)綁定方法
- 淺談Angularjs中不同類型的雙向數(shù)據(jù)綁定
- angularjs 的數(shù)據(jù)綁定實現(xiàn)原理
- Angular數(shù)據(jù)綁定機制原理
- AngularJS雙向數(shù)據(jù)綁定原理之$watch、$apply和$digest的應(yīng)用
- 解析Angular 2+ 樣式綁定方式
- 詳解Angular數(shù)據(jù)綁定及其實現(xiàn)方式
相關(guān)文章
Angular-UI Bootstrap組件實現(xiàn)警報功能
這篇文章主要介紹了Angular-UI Bootstrap組件實現(xiàn)警報功能,對Angular.js services的學習有所幫助,需要的朋友可以參考下2018-07-07AngularJS中的$watch(),$digest()和$apply()區(qū)分
這篇文章主要介紹了AngularJS中的$watch(),$digest()和$apply()區(qū)分,感興趣的朋友可以參考一下2016-04-04使用Angular Cli如何創(chuàng)建Angular私有庫詳解
這篇文章主要給大家介紹了關(guān)于使用Angular Cli如何創(chuàng)建Angular私有庫的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-01-01Angular directive遞歸實現(xiàn)目錄樹結(jié)構(gòu)代碼實例
本篇文章主要介紹了Angular directive遞歸實現(xiàn)目錄樹結(jié)構(gòu)代碼實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05angular和BootStrap3實現(xiàn)購物車功能
這篇文章主要為大家詳細介紹了angular和BootStrap3實現(xiàn)購物車功能的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01