Angularjs的$apply及其使用優(yōu)化

今天漠吻,我們要聊得是Angularjs中的小明星$apply。當(dāng)我們數(shù)據(jù)更新了司恳,但是view層卻沒反應(yīng)時途乃,總能聽到有人說,用apply吧扔傅,然后欺劳,懵懂無知的我們,在賦值代碼后面加了$scope.$apply(),然后就驚喜的發(fā)現(xiàn)铅鲤。噢划提,真的更新了。
然而邢享,有些時候鹏往,編譯器會無情的給你返回

Error: $digest already in progress

那么,導(dǎo)致這些現(xiàn)象的原因時什么的呢骇塘?$apply究竟干了啥伊履?聽我慢慢道來。

一.$apply的作用

$apply()函數(shù)可以從Angular框架的外部讓表達(dá)式在Angular上下文內(nèi)部執(zhí)行款违。

上面是AngularJs權(quán)威教程中的一句話唐瀑。什么意思呢?
首先插爹,你要清楚哄辣,在原生js或者第三方框架下请梢,修改model,是有可能不會觸發(fā)視圖更新的力穗,比如setTimeout毅弧、jquery插件。為什么当窗?因?yàn)樗麄兠撾x了Angularjs的上下文够坐,Angularjs并不能監(jiān)聽到數(shù)據(jù)的改變⊙旅妫看例子元咙。

1.setTimeout

html:

<p>{{name}}</p>

js:

$scope.name="張三";
setTimeout(function(){
$scope.name = '李四';
//$scope.$apply()
},500)

首先,name等于張三巫员,500ms后蛾坯,我把他賦值為李四,但是疏遏,頁面上并沒有改變脉课,依然是張三。
而财异,我們把$scope.$apply()放開倘零,就正常了,張三成功變?yōu)槔钏摹?/p>

2.第三方插件

html:

<p>Date: <input type="text" id="datepicker"></p>
<p>
<header>所選日期</header>
{{selectedDate}}
</p>

js:

$scope.selectedDate = '';
$( function() {
    $( "#datepicker" ).datepicker({
    onClose: function( selectedDate ) {
        $scope.selectedDate = selectedDate;
        // $scope.$apply();
    }
    });
} );

這是jquery的datepicker插件戳寸,當(dāng)我們選定日期后呈驶,下面的日期應(yīng)該隨之顯現(xiàn),而現(xiàn)在卻沒有疫鹊。這種情況就必須依靠$apply(),才能更新視圖袖瞻。

以上兩種情況,都因?yàn)椴惶幱贏ngularjs上下文中拆吆,導(dǎo)致監(jiān)聽不到數(shù)據(jù)的變化聋迎。而$apply究竟干了什么,才導(dǎo)致數(shù)據(jù)更新正常了呢枣耀?

其實(shí)$apply相當(dāng)于一個觸發(fā)器霉晕,它的作用就是觸發(fā)digest循環(huán),從而更新視圖捞奕。

在digest是Angularjs的核心牺堰,是它實(shí)現(xiàn)了神奇的數(shù)據(jù)綁定。凡是觸發(fā)事件颅围,必會觸發(fā)digest循環(huán)伟葫,比如,我們數(shù)值的ng事件院促,click啊筏养,change,實(shí)際上都是觸發(fā)了digest循環(huán)斧抱。

所以,我們所做的事撼玄,其實(shí)就是手動觸發(fā)了digest循環(huán)夺姑。關(guān)于digest循環(huán)墩邀,屬于題外話掌猛,這里不做過多介紹,想深入了解的同學(xué)眉睹,可以看看書籍荔茬,或者百度。

二.更好地運(yùn)用digest循環(huán)

在Angularjs中竹海,除了$apply可以觸發(fā)digest循環(huán)外慕蔚,還有其他的方法,也可以觸發(fā)此循環(huán)斋配。而且$apply往往時最壞的選擇孔飒。下面推薦一些更好的選擇。

1.$digest

$scope.$digest()的速度要比$apply要快艰争,因?yàn)樗桓庐?dāng)前作用域和子作用域的值坏瞄,對于父作用域時不管的。而$apply還要評估父作用域甩卓,這就大大消耗了性能鸠匀。

2.$timeout

$timeout去代替你的setTimeout,$timeout作為Angularjs的自帶服務(wù),當(dāng)然時更契合Angularjs環(huán)境啦逾柿。它會隱性觸發(fā)digest循環(huán)缀棍,而且它會延遲執(zhí)行,會在上一個digest循環(huán)完成后的下一刻机错,觸發(fā)digest循環(huán)爬范,這樣就不會出現(xiàn)上文所說的

$digest already in progress

我們把setTime的代碼放到$timeout

$timeout(function(){
$scope.name = '李四';
},500)

這就能正常工作了,看弱匪,沒有討厭的apply了坦敌!

3.$evalAsync

最推薦的應(yīng)該時這個方法了。如果當(dāng)前正好有一個digest循環(huán)在執(zhí)行痢法,那么它就會把導(dǎo)致digest循環(huán)的操作狱窘,放到當(dāng)前digest循環(huán)中去執(zhí)行。而$timeout是要等到當(dāng)前digest循環(huán)執(zhí)行完财搁,再執(zhí)行一次digest循環(huán)才可以蘸炸。所以evalAsync執(zhí)行更快,性能更好尖奔。我們可以像$timeout那樣去調(diào)用它搭儒,即

$scope.$evalAsync(
                    function( $scope ) {
                        console.log( "$evalAsync" );
                    }
                );

以上穷当,就是今天要說的全部內(nèi)容。Angularjs中還藏著許多奧秘淹禾,和更好的使用方法馁菜,希望大家可以深入地研究,分享出更好的文章铃岔。
下面是可執(zhí)行的代碼汪疮,大家可以探究探究
https://codepen.io/hanwolfxue/pen/yEZbYQ

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市毁习,隨后出現(xiàn)的幾起案子智嚷,更是在濱河造成了極大的恐慌,老刑警劉巖纺且,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盏道,死亡現(xiàn)場離奇詭異,居然都是意外死亡载碌,警方通過查閱死者的電腦和手機(jī)猜嘱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嫁艇,“玉大人朗伶,你說我怎么就攤上這事∩哑停” “怎么了腕让?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長歧斟。 經(jīng)常有香客問我纯丸,道長,這世上最難降的妖魔是什么静袖? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任觉鼻,我火速辦了婚禮,結(jié)果婚禮上队橙,老公的妹妹穿的比我還像新娘坠陈。我一直安慰自己,他們只是感情好捐康,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布仇矾。 她就那樣靜靜地躺著,像睡著了一般解总。 火紅的嫁衣襯著肌膚如雪贮匕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天花枫,我揣著相機(jī)與錄音刻盐,去河邊找鬼掏膏。 笑死,一個胖子當(dāng)著我的面吹牛敦锌,可吹牛的內(nèi)容都是我干的馒疹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼乙墙,長吁一口氣:“原來是場噩夢啊……” “哼颖变!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起伶丐,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤悼做,失蹤者是張志新(化名)和其女友劉穎疯特,沒想到半個月后哗魂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡漓雅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年录别,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邻吞。...
    茶點(diǎn)故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡组题,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出抱冷,到底是詐尸還是另有隱情崔列,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布旺遮,位于F島的核電站赵讯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏耿眉。R本人自食惡果不足惜边翼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鸣剪。 院中可真熱鬧组底,春花似錦、人聲如沸筐骇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽铛纬。三九已至厌均,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間饺鹃,已是汗流浹背莫秆。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工间雀, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人镊屎。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓惹挟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親缝驳。 傳聞我的和親對象是個殘疾皇子连锯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評論 2 353

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