如何理解angular自定義指令directive的scope屬性汗洒?

如何理解angular自定義指令directive的scope屬性?

目錄

1.背景介紹

2.知識(shí)剖析

3.常見問(wèn)題

4.解決方案

5.編碼實(shí)戰(zhàn)

6.擴(kuò)展思考

7.參考文獻(xiàn)

8.更多討論

1.背景介紹

指令定義

AngularJS與JQuery最大的區(qū)別表現(xiàn)在數(shù)據(jù)雙向綁定,實(shí)質(zhì)就是DOM的操作形式不一樣浑测。

? ? ? ? ? ? ? ? ? ? JQuery通過(guò)選擇器找到DOM元素杠输,再賦予元素的行為赎败;

? ? ? ? ? ? ? ? ? ? 而AngularJS則是,將指令與DOM綁定在一起蠢甲,再擴(kuò)展指令的行為僵刮。

? ? ? ? ? ? ? ? ? ? 例如, ng-click 可以讓一個(gè)元素能夠監(jiān)聽 click 事件鹦牛,并在接收到事件的時(shí)候執(zhí)行AngularJS表 達(dá)式搞糕。

? ? ? ? ? ? ? ? ? ? 我們可以自己創(chuàng)造新的指令。使用angular的directive( )這個(gè)模塊是用來(lái)定義指令的曼追。

2.知識(shí)剖析

一個(gè)完整的自定義指令所包含的內(nèi)容

angular.module(...);

? ? ? .directive('My-directive', function(injectables){

? ? ? ? restrict: 'A',

? ?   priority: 0,

? ?   template: '<div></div>',

? ?   templateUrl: 'directive.html',

? ?   replace: false,

? ?   transclude: false,

? ?   scope: false,

? ?   compile: function(tElement, tAttrs, transclude){

? ?     return{

? ?        pre:function preLink(scope, iElement, iAttrs, controller){ ... },

? ?        post:function postLink(scope, iElement, iAttrs, controller){ ... }

? ?     }

? ?   },

? ?   link: function(scope, iElement, iAttrs){ ... }

});


restrict(字符串)

restrict 是一個(gè)可選的參數(shù)寞宫。它告訴AngularJS這個(gè)指令在DOM中可以何種形式被聲明。默 認(rèn)AngularJS認(rèn)為 restrict 的值是 A 拉鹃,即以屬性的形式來(lái)進(jìn)行聲明辈赋。

restrict 值可以是以下幾種:

E 作為元素名使用

A 作為屬性使用

C 作為類名使用

M 作為注釋使用

template (字符串或函數(shù))

template 參數(shù)是可選的,必須被設(shè)置為以下兩種形式之一:

? 一段HTML文本膏燕;

? 一個(gè)可以接受兩個(gè)參數(shù)的函數(shù)钥屈,參數(shù)為 tElement 和 tAttrs ,并返回一個(gè)代表模板的字符 串坝辫。

templateUrl篷就,引入外部的一個(gè)html文件

指令中的SCOPE

? ? ? ? ? ? ? ? directive 默認(rèn)能共享父 scope 中定義的屬性,例如在模版中直接使用父 scope 中的對(duì)象和屬性近忙。

? ? ? ? ? ? ? ? 通常使用這種直接共享的方式可以實(shí)現(xiàn)一些簡(jiǎn)單的 directive 功能竭业。但是當(dāng)要?jiǎng)?chuàng)建一個(gè)可以重復(fù)使用的

? ? ? ? ? ? ? ? directive的時(shí)候, 就不能依賴于父scope了及舍,因?yàn)樵诓煌牡胤绞褂胐irective對(duì)應(yīng)的父scope不一樣未辆。

? ? ? ? ? ? ? ? 所以需要一個(gè)隔離的scope。


2.2 scope屬性的3種取值

①锯玛、false(默認(rèn)值):直接使用父scope咐柜。

②、true:繼承父scope

③攘残、對(duì)象{ }:創(chuàng)建一個(gè)新的“隔離”scope拙友,但仍可與父scope通信。隔離的scope歼郭,通常用于創(chuàng)建可復(fù)用的指令遗契,也就是它不用管父scope中的model。然而雖然說(shuō)是“隔離”病曾,但通常我們還是需要讓這個(gè)子scope跟父scope中的變量進(jìn)行綁定牍蜂。綁定的策略有3種:@漾根、=、&捷兰。

@ 這是一個(gè)單項(xiàng)綁定的前綴標(biāo)識(shí)符

使用方法:在元素中使用屬性立叛,好比這樣 my-name="{{name}}",注意贡茅,屬性的名字要用-將兩個(gè)單詞連接秘蛇,因?yàn)槭菙?shù)據(jù)的單項(xiàng)綁定所以要通過(guò)使用{{}}來(lái)綁定數(shù)據(jù)。

= 這是一個(gè)雙向數(shù)據(jù)綁定前綴標(biāo)識(shí)符

使用方法:在元素中使用屬性顶考,好比這樣 my-age="age",注意赁还,數(shù)據(jù)的雙向綁定要通過(guò)=前綴標(biāo)識(shí)符實(shí)現(xiàn),所以不可以使用{{}}驹沿。


& 這是一個(gè)綁定函數(shù)方法的前綴標(biāo)識(shí)符

使用方法:在元素中使用屬性艘策,好比這樣 my-change="changeAge()",注意渊季,屬性的名字要用-將多個(gè)個(gè)單詞連接朋蔫。

指令中的 CONTROLLER , COMPILE , LINK函數(shù)

AngularJs 的生命周期;分為兩個(gè)階段:

第一個(gè)階段是編譯階段: 在編譯階段,AngularJS會(huì)遍歷整個(gè)HTML文檔并根據(jù)JavaScript中的指令定義來(lái)處理頁(yè)面上聲明的指令却汉。

? ? ? ? ? ? ? ? ? 每一個(gè)指令的模板中都可能含 有另外一個(gè)指令驯妄,另外一個(gè)指令也可能會(huì)有自己的模板。當(dāng)AngularJS調(diào)用HTML文檔根部的指令時(shí)合砂,

? ? ? ? ? ? ? ? ? 會(huì)遍歷其中所有的模板青扔,模板中也可能包 含帶有模板的指令.一旦對(duì)指令和其中的子模板進(jìn)行遍歷或編譯,

? ? ? ? ? ? ? ? ? 編譯后的模板會(huì)返回一個(gè)叫做模板函數(shù)的函數(shù)翩伪。我們有機(jī)會(huì)在指令的模板函 數(shù)被返回前微猖,對(duì)編譯后的DOM樹進(jìn)行修改。

第二個(gè)階段是鏈接階段:鏈接函數(shù)來(lái)將模板與作用域鏈接起來(lái);負(fù)責(zé)設(shè)置事件監(jiān)聽器缘屹,監(jiān)視數(shù)據(jù)變化和實(shí)時(shí)的操作DOM.鏈接函數(shù)是可選的凛剥。

如果定義了編譯函數(shù),它會(huì)返回鏈接函數(shù)囊颅,因此當(dāng)兩個(gè)函數(shù)都定義了時(shí)当悔,編譯函數(shù)會(huì)重載鏈接函數(shù)

? ? ? ? ? ? ? ? 指令的控制器和link函數(shù)可以進(jìn)行互換√叽控制器主要是用來(lái)提供可在指令間復(fù)用的行為,但鏈接函數(shù)只能在當(dāng)前內(nèi)部指令中定義行為嗅骄,

? ? ? ? ? ? ? ? 且無(wú)法在指令間復(fù)用.link函數(shù)可以將指令互相隔離開來(lái)胳挎,而controller則定義可復(fù)用的行為。


3.常見問(wèn)題

scope屬性的3種取值對(duì)指令有什么影響?

4.解決方案

每當(dāng)一個(gè)指令被創(chuàng)建的時(shí)候溺森,都會(huì)有這樣一個(gè)選擇慕爬,是繼承自己的父作用域(一般是外部的Controller提供的作用域或者根作用域($rootScope))窑眯,還是創(chuàng)建一個(gè)新的自己的作用域,當(dāng)然AngularJS為我們指令的scope參數(shù)提供了三種選擇医窿,分別是:false,true,{}磅甩;默認(rèn)情況下是false。

當(dāng)scope參數(shù)被設(shè)置為false時(shí)有什么情況發(fā)生在這種情況下姥卢,在指令模板中可以直接使用父作用域中的變量卷要,函數(shù)


<div ng-controller="MyCtrl"class="div1">

? ? ? ? ? ? ? ? ? ? Ctrl:<br>

? ? ? ? ? ? ? ? ? ? <input ng-model="userName">{{userName}}<br>

? ? ? ? ? ? ? ? ? ? Directive:<br>

? ? ? ? ? ? ? ? ? ? <hello></hello>

? ? ? ? ? ? ? ? ? ? ? ? 兄弟<br>

? ? ? ? ? ? ? ? ? ? <hello></hello>

? ? ? ? ? ? ? ? ? ? </div>

? ? ? ? ? ? angular.module("app",[])

? ? ? ? ? ? //測(cè)試true和false

.controller("MyCtrl",function($scope){

? ? ? ? ? ? ? ? ? ? ? ? ? ? $scope.userName="山水";

})

? ? ? ? ? ? ? ? ? ? ? ? .directive("hello",function() {

return{

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? restrict:"AECM",

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? template:'<div><input type="text" ng-model="userName">{{userName}}</div>',

replace:true,

scope:false? ? ? ? ? ? ? }

})


因?yàn)槲覀儗cope的屬性設(shè)置為false所以,我們創(chuàng)建的指令繼承了父作用域的一切屬性和方法独榴,這也使得在指令的模板中我們可以使用這些屬性和方法僧叉。

注意:此時(shí)我們?cè)谳斎肟蚶锔淖兠郑瑫?huì)發(fā)現(xiàn)上面的兩個(gè)名字都發(fā)生了變化

4.2 scope = true棺榔。

當(dāng)把scope屬性設(shè)置為true時(shí)瓶堕,這表明我們創(chuàng)建的指令要?jiǎng)?chuàng)建一個(gè)新的作用域,這個(gè)作用域繼承自我們的父作用域症歇。


修改上面的JS代碼郎笆,將指令中的:scope:false修改為scope:true "


然后我們?cè)僭囍谖覀兊膇nput輸入框中寫一些字符串,會(huì)發(fā)現(xiàn)忘晤,指令中的那個(gè)name發(fā)生了變化宛蚓,但是指令外的那個(gè)name卻沒(méi)有發(fā)生變化,這說(shuō)明了一個(gè)問(wèn)題德频。

當(dāng)我們將scope設(shè)置為true的時(shí)候苍息,我們就新創(chuàng)建了一個(gè)作用域,只不過(guò)這個(gè)作用域是繼承了我們的父作用域壹置;我覺得可以這樣理解竞思,我們新創(chuàng)建的作用域是一個(gè)新的作用域,只不過(guò)在初始化的時(shí)候钞护,用了父作用域的屬性和方法去填充我們這個(gè)新的作用域盖喷。它和父作用域不是同一個(gè)作用域。

當(dāng)我們將scope設(shè)置為false的時(shí)候,我們創(chuàng)建的指令和父作用域(其實(shí)是同一個(gè)作用域)共享同一個(gè)model模型难咕,所以在指令中修改模型數(shù)據(jù)课梳,它會(huì)反映到父作用域的模型中。

4.3 scope = {}

當(dāng)我們將scope的屬性設(shè)置為{}時(shí)余佃,我們可以做更多的事情暮刃。

AngularJS最強(qiáng)的大的地方之一就是它可以構(gòu)建組件,無(wú)論放在哪里都是可以使用的爆土;這所以可以做到這些椭懊,不得不歸功于指令的這個(gè)屬性;當(dāng)我們將scope設(shè)置為{}時(shí)步势,意味著我們創(chuàng)建的一個(gè)新的與父作用域隔離的新的作用域氧猬,這使我們?cè)诓恢劳獠凯h(huán)境的情況下背犯,就可以正常工作,不依賴外部環(huán)境盅抚。


我們使用了隔離的作用域漠魏,不代表我們不可以使用父作用域的屬性和方法。

我們可以通過(guò)向scope的{}中傳入特殊的前綴標(biāo)識(shí)符(即prefix)妄均,來(lái)進(jìn)行數(shù)據(jù)的綁定柱锹。

在創(chuàng)建了隔離的作用域,我們可以通過(guò)@,&,=引用應(yīng)用指令的元素的屬性

下面我們來(lái)看看如何使用這些前綴標(biāo)識(shí)符:

1.@:?jiǎn)蜗蚪壎ù曰蓿獠縮cope能夠影響內(nèi)部scope奕纫,但反過(guò)來(lái)不成立;

這是一個(gè)單項(xiàng)綁定的前綴標(biāo)識(shí)符烫沙。使用方法:在元素中使用屬性匹层,好比這樣? ? ? ? ? ??

<div my-directive="" my-name="{{name}}"></div>


注意,屬性的名字要用-將兩個(gè)單詞連接锌蓄,因?yàn)槭菙?shù)據(jù)的單項(xiàng)綁定所以要通過(guò)使用{{}}來(lái)綁定數(shù)據(jù)升筏。

2、=:雙向綁定瘸爽,外部scope和內(nèi)部scope的model能夠相互改變您访;

這是一個(gè)雙向數(shù)據(jù)綁定前綴標(biāo)識(shí)符。使用方法:在元素中使用屬性剪决,好比這樣? ? ? ? ? ? ? ?

<div my-directive="" my-name="name"></div>


注意灵汪,數(shù)據(jù)的雙向綁定要通過(guò)=前綴標(biāo)識(shí)符實(shí)現(xiàn),所以不可以使用{{}}柑潦。

3享言、&:把內(nèi)部scope的函數(shù)的返回值和外部scope的任何屬性綁定起來(lái)。

這是一個(gè)綁定函數(shù)方法的前綴標(biāo)識(shí)符渗鬼。使用方法:在元素中使用屬性览露,好比這樣

<div test-directive=""action="click()"></div>


注意,屬性的名字要用-將多個(gè)個(gè)單詞連接譬胎。

5.編碼實(shí)戰(zhàn)

6.擴(kuò)展思考

我們的指令是如何利用這些前綴標(biāo)識(shí)符來(lái)尋找我們想要的屬性或者函數(shù)的差牛?

@ 當(dāng)指令編譯到模板的name時(shí),就會(huì)到scope中尋找是否含有name的鍵值對(duì)堰乔,如果存在偏化,就像上面那樣,看到@就知道這是一個(gè)單向的數(shù)據(jù)綁定镐侯,然后尋找原來(lái)的那個(gè)使用指令的元素上(或者是指令元素本身)含有這個(gè)值的屬性即my-name={{name}}夹孔,然后在父作用域查找{{name}}的值,得到之后傳遞給模板中的name析孽。

=和&與@差不多搭伤,只不過(guò)=進(jìn)行的是雙向的數(shù)據(jù)綁定,不論模板還是父作用域上的屬性的值發(fā)生改變都會(huì)使另一個(gè)值發(fā)生改變袜瞬,而&是綁定函數(shù)而已怜俐。

7.參考文獻(xiàn)

參考一:AngularJS 自定義指令

參考二:一招制敵 - 玩轉(zhuǎn) AngularJS 指令的 Scope (作用域)

8.更多討論

鳴謝

感謝大家觀看



今天的分享就到這里啦,歡迎大家點(diǎn)贊邓尤、轉(zhuǎn)發(fā)拍鲤、留言、拍磚~

技能樹.IT修真院???

? “我們相信人人都可以成為一個(gè)工程師汞扎,現(xiàn)在開始季稳,找個(gè)師兄,帶你入門澈魄,掌控自己學(xué)習(xí)的節(jié)奏景鼠,學(xué)習(xí)的路上不再迷茫”痹扇。

? ?這里是技能樹.IT修真院铛漓,成千上萬(wàn)的師兄在這里找到了自己的學(xué)習(xí)路線,學(xué)習(xí)透明化鲫构,成長(zhǎng)可見化浓恶,師兄1對(duì)1免費(fèi)指導(dǎo)。

? ?快來(lái)與我一起學(xué)習(xí)吧~http://www.jnshu.com/login/1/21109035

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末结笨,一起剝皮案震驚了整個(gè)濱河市包晰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌炕吸,老刑警劉巖伐憾,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異算途,居然都是意外死亡塞耕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門嘴瓤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)扫外,“玉大人,你說(shuō)我怎么就攤上這事廓脆∩秆瑁” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵停忿,是天一觀的道長(zhǎng)驾讲。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么吮铭? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任时迫,我火速辦了婚禮,結(jié)果婚禮上谓晌,老公的妹妹穿的比我還像新娘掠拳。我一直安慰自己,他們只是感情好纸肉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布溺欧。 她就那樣靜靜地躺著,像睡著了一般柏肪。 火紅的嫁衣襯著肌膚如雪姐刁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天烦味,我揣著相機(jī)與錄音聂使,去河邊找鬼。 笑死拐叉,一個(gè)胖子當(dāng)著我的面吹牛岩遗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凤瘦,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼宿礁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蔬芥?” 一聲冷哼從身側(cè)響起梆靖,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎笔诵,沒(méi)想到半個(gè)月后返吻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乎婿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年测僵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谢翎。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡捍靠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出森逮,到底是詐尸還是另有隱情榨婆,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布褒侧,位于F島的核電站良风,受9級(jí)特大地震影響谊迄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜烟央,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一统诺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吊档,春花似錦篙议、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)移怯。三九已至香璃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間舟误,已是汗流浹背葡秒。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嵌溢,地道東北人眯牧。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像赖草,于是被迫代替她去往敵國(guó)和親学少。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容