欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
再談angularJS數據綁定機制及背后原理

這篇是對angularJS的一些疑點(diǎn)回顧,是對目前angularJS開(kāi)發(fā)的各種常見(jiàn)問(wèn)題的整理匯總。如果對文中的題目全部了然于胸,覺(jué)得對整個(gè)angular框架應該掌握的七七八八了。希望志同道合的通知補充內容

Angular 的數據綁定采用什么機制,詳述原理?

臟檢查機制。闡釋臟檢查機制,必須先了解如下問(wèn)題。

單向綁定(ng-bind) 和 雙向綁定(ng-model) 的區別?

ng-bind 單向數據綁定($scope -> view),用于數據顯示,簡(jiǎn)寫(xiě)形式是 {{}}。

兩者的區別在于頁(yè)面沒(méi)有加載完畢 {{val}} 會(huì )直接顯示到頁(yè)面,直到 Angular 渲染該綁定數據(這種行為有可能將 {{val}} 讓用戶(hù)看到);而 ng-bind 則是在 Angular 渲染完畢后將數據顯示。

ng-model 是雙向數據綁定(scope?>viewandview?>scope),用于綁定值會(huì )變化的表單元素等。

雙向數據綁定是 AngularJS 的核心機制之一。當 view 中有任何數據變化時(shí),會(huì )更新到 model ,當 model 中數據有變化時(shí),view 也會(huì )同步更新,顯然,這需要一個(gè)監控。

 

雙向數據綁定的原理?

Angular 在 scope 模型上設置了一個(gè) 監聽(tīng)隊列,用來(lái)監聽(tīng)數據變化并更新 view 。

   每次綁定一個(gè)東西到 view 上時(shí) AngularJS 就會(huì )往 watchwatch,用來(lái)檢測它監視的 model 里是否有變化的東西。    

當你寫(xiě)下表達式如{{ val }}時(shí),AngularJS在幕后會(huì )為你在scope模型上設置一個(gè)watcher(表達式將被 Angular 編譯成一個(gè)監視函數),它用來(lái)在數據發(fā)生變化的時(shí)候更新view。這里的watcher和你會(huì )在A(yíng)ngularJS中設置的watcher是一樣的:

1
2
3
$scope.$watch('val'function(newValue, oldValue) {
  //update the DOM with newValue
});
  • 將數據附加到 Scope 上,數據自身不會(huì )對性能產(chǎn)生影響,如果沒(méi)有監視器來(lái)監視這個(gè)屬性,那個(gè)這個(gè)屬性在不在 Scope 上是無(wú)關(guān)重要的;Angular 并不會(huì )遍歷 Scope 上的屬性,它將遍歷所有的觀(guān)察器。

  • 每個(gè)監視函數是在每次 $digest 過(guò)程中被調用的。因此,我們要注意觀(guān)察器的數量以及每個(gè)監視函數或者監視表達式的性能。

 

 

$digest循環(huán)是在什么時(shí)候以各種方式開(kāi)始的?

當瀏覽器接收到可以被 angular context 處理的事件時(shí),digest環(huán)會(huì )發(fā),watch,最后更新 dom。

舉個(gè)栗子

1
<button ng-click="val=val+1">increase 1</button>

click 時(shí)會(huì )產(chǎn)生一次更新的操作(至少觸發(fā)兩次 $digest 循環(huán))

  • 按下按鈕

  • 瀏覽器接收到一個(gè)事件,進(jìn)入到 angular context

  • digest環(huán)開(kāi),詢(xún)個(gè)watch 是否變化

  • 由于監視 scope.valwatch 報告了變化,因此強制再執行一次 $digest 循環(huán)

  • 新的 $digest 循環(huán)未檢測到變化

  • 瀏覽器拿回控制器,更新 $scope. val.新值對應的 dom

 

在調用了scope.digest()后,digest環(huán)開(kāi)。個(gè)ng?clickhandlerscope,時(shí)AngularJS會(huì )動(dòng)過(guò)調digest()來(lái)觸發(fā)一輪digest環(huán)。digest循環(huán)開(kāi)始后,它會(huì )觸發(fā)每個(gè)watcher。這些watchers會(huì )檢查scope中的當前model值是否和上一次計算得到的model值不同。如果不同,那么對應的回調函數會(huì )被執行。調用該函數的結果,就是view中的表達式內容(譯注:諸如{{ val }})會(huì )被更新。除了ng-click指令,還有一些其它的built-in指令以及服務(wù)來(lái)讓你更改models(比如ng-model,timeout)動(dòng)發(fā)digest循環(huán)。

目前為止還不錯!但是,有一個(gè)小問(wèn)題。在上面的例子中,AngularJS并不直接調用digest(),調scope.apply(),會(huì )調rootScope.$digest()。因此,一輪digest環(huán)rootScope開(kāi)始,隨后會(huì )訪(fǎng)問(wèn)到所有的children scope中的watchers。

通常寫(xiě)代碼時(shí)我們無(wú)需主動(dòng)調用 applydigest 是因為 angular 在外部對我們的回調函數做了包裝。例如常用的 ng-click,這是一個(gè)指令(Directive),內部實(shí)現則 類(lèi)似 于

1
2
3
DOM.addEventListener('click'function ($scope) {
  $scope.$apply(() => userCode());
});

可以看到:ng-click 幫我們做了 apply個(gè)。類(lèi)調,http、timeout。聽(tīng)說(shuō)angular個(gè),實(shí)務(wù)Service,調scope.$apply。

現在,假設你將ng-click指令關(guān)聯(lián)到了一個(gè)button上,并傳入了一個(gè)function名到ng-click上。當該button被點(diǎn)擊時(shí),AngularJS會(huì )將此function包裝到一個(gè)wrapping function中,然后傳入到scope.apply()。因此,你的function會(huì )正常被執行,修改models(如果需要的話(huà)),此時(shí)一輪$digest循環(huán)也會(huì )被觸發(fā),用來(lái)確保view也會(huì )被更新。

 

Note: scope.apply()會(huì )自動(dòng)地調用rootScope.digest()。apply()。會(huì )個(gè)function,function發(fā)digest循環(huán)。第二種會(huì )不接受任何參數,只是觸發(fā)一輪$digest循環(huán)。我們馬上會(huì )看到為什么第一種形式更好。

 

$digest 循環(huán)會(huì )運行多少次?

$digest 循環(huán)的上限是 10 次(超過(guò) 10次后拋出一個(gè)異常,防止無(wú)限循環(huán))。

$digest 循環(huán)不會(huì )只運行一次。在當前的一次循環(huán)結束后,它會(huì )再執行一次循環(huán)用來(lái)檢查是否有 models 發(fā)生了變化。

這就是臟檢查(Dirty Checking),它用來(lái)處理在 listener 函數被執行時(shí)可能引起的 model 變化。因此 digest環(huán)會(huì )model發(fā),digest 循環(huán)的次數達到了 10 次(超過(guò) 10 次后拋出一個(gè)異常,防止無(wú)限循環(huán))。

當 $digest 循環(huán)結束時(shí),DOM 相應地變化。

臟檢查如何被觸發(fā)?

angular 會(huì )在可能觸發(fā) UI 變更的時(shí)候進(jìn)行臟檢查:這句話(huà)并不準確。實(shí)際上,

臟檢查是digest執行的,另一個(gè)更常用的用于觸發(fā)臟檢查的函數apply——其實(shí)就是 $digest 的一個(gè)簡(jiǎn)單封裝(還做了一些抓異常的工作)。

通常寫(xiě)代碼時(shí)我們無(wú)需主動(dòng)調用 applydigest 是因為 angular 在外部對我們的回調函數做了包裝。例如常用的 ng-click,這是一個(gè)指令(Directive),內部實(shí)現則 類(lèi)似于

1
2
3
DOM.addEventListener('click'function ($scope) {
  $scope.$apply(() => userCode());
});

angular對常用的dom事件,xhq事件作了封裝,如果調用這些封裝,就會(huì )在里面觸發(fā)進(jìn)入angular的digest流程,主要有以下情況:

  • DOM事件,如用戶(hù)輸入文本,點(diǎn)擊按鈕等,(ng-click)

  • XHQ響應事件($http)

  • 瀏覽器Location變更事件,即Url中hash部分變更($location)

  • Timer事件(Timeout,interval)

  • 手動(dòng)調用applydigest

 

apply()digest() 的區別?

 

applyscope(或者是 direcvie 里的 link 函數中的 scope)的一個(gè)函數,調用它會(huì )強制一次 digest環(huán)環(huán),會(huì )個(gè),apply 的標志)。

apply()digest() 有兩個(gè)區別。

  • 1) 最直接的差異是, $apply 可以帶參數,它可以接受一個(gè)函數,然后在應用數據之后,調用這個(gè)函數。所以,一般在集成非 Angular 框架(比如jQuery)的代碼時(shí),可以把代碼寫(xiě)在這個(gè)里面調用。

  • 2) 當調用 digest時(shí),發(fā),調apply 的時(shí)候,會(huì )觸發(fā)作用域樹(shù)上的所有監控。

什么時(shí)候手動(dòng)調用 $apply() 方法?

取決于是否在 Angular 上下文環(huán)境(angular context)。

AngularJS對此有著(zhù)非常明確的要求,就是它只負責對發(fā)生于A(yíng)ngularJS上下文環(huán)境中的變更會(huì )做出自動(dòng)地響應(即,在apply()發(fā)models)。AngularJSbuilt?in,model會(huì )view。,AngularJSmodel,過(guò)動(dòng)調apply()來(lái)通知AngularJS。這就像告訴AngularJS,你修改了一些models,希望AngularJS幫你觸發(fā)watchers來(lái)做出正確的響應。

典型的需要調用 $apply() 方法的場(chǎng)景是:

  • 1) 使用了 JavaScript 中的 setTimeout() 來(lái)更新一個(gè) scope model

  • 2) 用指令設置一個(gè) DOM 事件 listener 并且在該 listener 中修改了一些 models

場(chǎng)景一

1
2
3
4
5
6
7
$scope.setMsg = function() {
    setTimeout(function() {
        $scope.message = 'hello world';
        console.log('message:' + $scope.message);
    }, 2000);
}
$scope.setMsg();

運行這個(gè)例子,會(huì )看到過(guò)了兩秒鐘之后,控制臺確實(shí)會(huì )顯示出已經(jīng)更新的 model,然而,view 并沒(méi)有更新。

scope.getMessageapply() 方法。

1
2
3
4
5
6
7
8
$scope.getMessage = function() {
    setTimeout(function() {
        $scope.$apply(function() {
            $scope.message = 'hello world';
            console.log('message:' + $scope.message);
        });
    }, 2000);
}

再運行就 OK 了。

 

不過(guò),在 AngularJS 中應該盡量使用 timeoutService來(lái)setTimeout(),會(huì )調apply(),讓你不需要手動(dòng)地調用它。

場(chǎng)景二

實(shí)現一個(gè) click 的指令,類(lèi)似以下功能,directive 的編寫(xiě)如下:

1
2
3
4
5
6
7
app.directive("inc"function() {
    return function (scope, element, attr) {
        element.on("click"function() {
            scope.val++;
        });
    };
});

 

跟場(chǎng)景一的結果一樣,這個(gè)時(shí)候,點(diǎn)擊按鈕,界面上的數字并不會(huì )增加。但查看調試器,發(fā)現數據確實(shí)已經(jīng)增加了。

在 scope.val++; 一行后面添加 scope.apply();scope.digest(); 就 OK 了。

$apply() 方法的兩種形式

1
2
3
4
5
6
//無(wú)參
$scope.$apply()
//有參
$scope.$apply(function(){
    ...
})

應該總使用接受一個(gè) function 作為參數的 apply()。個(gè)functionapply() 中的時(shí)候,這個(gè) function 會(huì )被包裝到一個(gè) try…catch 塊中,所以一旦有異常發(fā)生,該異常會(huì )被 $exceptionHandler service 處理。

 

想象一下如果有個(gè) alert 框顯示錯誤給用戶(hù),然后有個(gè)第三方的庫進(jìn)行一個(gè)網(wǎng)絡(luò )調用然后失敗了,如果不把它封裝進(jìn) $apply 里面,Angular 永遠不會(huì )知道失敗了,alert 框就永遠不會(huì )彈出來(lái)了。

在 AngularJS 中使用 $watch注意事項?

如果要監聽(tīng)的是一個(gè)對象,那還需要第三個(gè)參數

1
2
3
4
5
$scope.data.name = 'htf';
$scope.$watch('data'function(newValue, oldValue) {
    if (newValue === oldValue) { return; }
    $scope.updated++;
}, true);

表示比較的是對象的值而不是引用,如果不加第三個(gè)參數 true ,在 data.name 變化時(shí),不會(huì )觸發(fā)相應操作,因為引用的是同一引用。

臟檢查的范圍

前面說(shuō)到:angular 會(huì )對所有綁定到 UI 上的表達式做臟檢查。其實(shí),在 angular 實(shí)現內部,所有綁定表達式都被轉換為 scope.watch()。每個(gè) watch。ng?bind="a"scope.watch(a,callback),scope.$watch 可不會(huì )管被 watch 的表達式是否跟觸發(fā)臟檢查的事件有關(guān)。

例如:

1
2
3
4
5
<div ng-show="false">
  <span id="span1" ng-bind="content"></span>
</div>
<span id="span2" ng-bind="content"></span>
<button ng-click="">TEST</button>

問(wèn):點(diǎn)擊 TEST 這個(gè)按鈕時(shí)會(huì )觸發(fā)臟檢查嗎?觸發(fā)幾次?

首先:ng-click="" 什么都沒(méi)有做。angular 會(huì )因為這個(gè)事件回調函數什么都沒(méi)做就不進(jìn)行臟檢查嗎?不會(huì )。

然后:#span1 被隱藏掉了,會(huì )檢查綁定在它上面的表達式嗎?盡管用戶(hù)看不到,但是 scope.watch('content', callback) 還在。就算你直接把這個(gè) span 元素干掉,只要 watch 表達式還在,要檢查的還會(huì )檢查。

再次:重復的表達式會(huì )重復檢查嗎?會(huì )。

最后:別忘了 ng-show="false"??赡苁且驗?angular 的開(kāi)發(fā)人員認為這種綁定常量的情況并不多見(jiàn),所以 $watch 并沒(méi)有識別所監視的表達式是否是常量。常量依舊會(huì )重復檢查。

所以:

答:觸發(fā)三次。一次 false,一次 content,一次 content

所以說(shuō)一個(gè)綁定表達式只要放在當前 DOM 樹(shù)里就會(huì )被監視,不管它是否可見(jiàn),不管它是否被放在另一個(gè) Tab 里,更不管它是否與用戶(hù)操作相關(guān)。

另外,就算在不同 Controller 里構造的 scope會(huì ),angularrootScope,你還可以 scope.emit。angular 無(wú)法保證你絕對不會(huì )在一個(gè) controller 里更改另一個(gè) controller 生成的 scope,包括 自定義指令(Directive)生成的 scope 和 Angular 1.5 里新引入的組件(Component)。

所以說(shuō)不要懷疑用戶(hù)在輸入表單時(shí) angular 會(huì )不會(huì )監聽(tīng)頁(yè)面左邊導航欄的變化。

如何優(yōu)化臟檢查與運行效率

臟檢查慢嗎?

說(shuō)實(shí)話(huà)臟檢查效率是不高,但是也談不上有多慢。簡(jiǎn)單的數字或字符串比較能有多慢呢?十幾個(gè)表達式的臟檢查可以直接忽略不計;上百個(gè)也可以接受;成百上千個(gè)就有很大問(wèn)題了。綁定大量表達式時(shí)請注意所綁定的表達式效率。建議注意一下幾點(diǎn):

  • 表達式(以及表達式所調用的函數)中少寫(xiě)太過(guò)復雜的邏輯

  • 不要連接太長(cháng)的 filter(往往 filter 里都會(huì )遍歷并且生成新數組)

  • 不要訪(fǎng)問(wèn) DOM 元素。

1、使用單次綁定減少綁定表達式數量
單次綁定(One-time binding 是 Angular 1.3 就引入的一種特殊的表達式,它以 :: 開(kāi)頭,當臟檢查發(fā)現這種表達式的值不為 undefined 時(shí)就認為此表達式已經(jīng)穩定,并取消對此表達式的監視。這是一種行之有效的減少綁定表達式數量的方法,與 ng-repeat 連用效果更佳(下文會(huì )提到),但過(guò)度使用也容易引發(fā) bug。

2、善用 ng-if 減少綁定表達式的數量

 

如果你認為 ng-if 就是另一種用于隱藏、顯示 DOM 元素的方法你就大錯特錯了。

ng-if 不僅可以減少 DOM 樹(shù)中元素的數量(而非像 ng-hide 那樣僅僅只是加個(gè) display: none),每一個(gè) ng-if 擁有自己的 scope,ng-if 下面的 $watch 表達式都是注冊在 ng-if 自己 scope 中。當 ng-if 變?yōu)?false,ng-if 下的 scope 被銷(xiāo)毀,注冊在這個(gè) scope 里的綁定表達式也就隨之銷(xiāo)毀了。

考慮這種 Tab 選項卡實(shí)現:

1
2
3
4
5
6
7
8
9
10
<ul>
  <li ng-class="{ selected: selectedTab === 1 }">Tab 1 title</li>
  <li ng-class="{ selected: selectedTab === 2 }">Tab 2 title</li>
  <li ng-class="{ selected: selectedTab === 3 }">Tab 3 title</li>
  <li ng-class="{ selected: selectedTab === 4 }">Tab 4 title</li>
</ul>
<div ng-show="selectedTab === 1">[[Tab 1 body...]]</div>
<div ng-show="selectedTab === 2">[[Tab 2 body...]]</div>
<div ng-show="selectedTab === 3">[[Tab 3 body...]]</div>
<div ng-show="selectedTab === 4">[[Tab 4 body...]]</div>

對于這種會(huì )反復隱藏、顯示的元素,通常人們第一反應都是使用 ng-show 或 ng-hide 簡(jiǎn)單的用 display: none 把元素設置為不可見(jiàn)。

然而入上文所說(shuō),肉眼不可見(jiàn)不代表不會(huì )跑臟檢查。如果將 ng-show 替換為 ng-if 或 ng-switch-when

1
2
3
4
<div ng-if="selectedTab === 1">[[Tab 1 body...]]</div>
<div ng-if="selectedTab === 2">[[Tab 2 body...]]</div>
<div ng-if="selectedTab === 3">[[Tab 3 body...]]</div>
<div ng-if="selectedTab === 4">[[Tab 4 body...]]</div>

有如下優(yōu)點(diǎn):

  • 首先 DOM 樹(shù)中的元素個(gè)數顯著(zhù)減少至四分之一,降低內存占用

  • 其次 $watch 表達式也減少至四分之一,提升臟檢查循環(huán)的速度

  • 如果這個(gè) tab 下面有 controller(例如每個(gè) tab 都被封裝為一個(gè)組件),那么僅當這個(gè) tab 被選中時(shí)該 controller 才會(huì )執行,可以減少各頁(yè)面的互相干擾

  • 如果 controller 中調用接口獲取數據,那么僅當對應 tab 被選中時(shí)才會(huì )加載,避免網(wǎng)絡(luò )擁擠

當然也有缺點(diǎn):

  • DOM 重建本身費時(shí)間

  • 如果 tab 下有 controller,那么每次該 tab 被選中時(shí) controller 都會(huì )被執行

  • 如果在 controller 里面調接口獲取數據,那么每次該 tab 被選中時(shí)都會(huì )重新加載

  • 各位讀者自己取舍。

3、給 ng-repeat 手工添加 track by

不恰當的 ng-repeat 會(huì )造成 DOM 樹(shù)反復重新構造,拖慢瀏覽器響應速度,造成頁(yè)面閃爍。除了上面這種比較極端的情況,如果一個(gè)列表頻繁拉取 Server 端數據自刷新的話(huà)也一定要手工添加 track by,因為接口給前端的數據是不可能包含 $$hashKey 這種東西的,于是結果就造成列表頻繁的重建。

其實(shí)不必考慮那么多,總之加上沒(méi)壞處,至少可以避免 angular 生成 $$hashKey 這種奇奇怪怪的東西。

具體參看: 詳解track by

 

臟檢測的利弊?

很多人對Angular的臟檢測機制感到不屑,推崇基于setter,getter的觀(guān)測機制,在我看來(lái),這只是同一個(gè)事情的不同實(shí)現方式,并沒(méi)有誰(shuí)完全勝過(guò)誰(shuí),兩者是各有優(yōu)劣的。

 

大家都知道,在循環(huán)中批量添加DOM元素的時(shí)候,會(huì )推薦使用DocumentFragment,為什么呢,因為如果每次都對DOM產(chǎn)生變更,它都要修改DOM樹(shù)的結構,性能影響大,如果我們能先在文檔碎片中把DOM結構創(chuàng )建好,然后整體添加到主文檔中,這個(gè)DOM樹(shù)的變更就會(huì )一次完成,性能會(huì )提高很多。

同理,在A(yíng)ngular框架里,考慮到這樣的場(chǎng)景:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function TestCtrl($scope) {
    $scope.numOfCheckedItems = 0;
    var list = [];
    for (var i=0; i<10000; i++) {
        list.push({
            index: i,
            checked: false
        });
    }
    $scope.list = list;
    $scope.toggleChecked = function(flag) {
        for (var i=0; i<list.length; i++) {
            list[i].checked = flag;
            $scope.numOfCheckedItems++;
        }
    };
}

如果界面上某個(gè)文本綁定這個(gè)numOfCheckedItems,會(huì )怎樣?在臟檢測的機制下,這個(gè)過(guò)程毫無(wú)壓力,一次做完所有數據變更,然后整體應用到界面上。這時(shí)候,基于setter的機制就慘了,除非它也是像Angular這樣把批量操作延時(shí)到一次更新,否則性能會(huì )更低。

 

所以說(shuō),兩種不同的監控方式,各有其優(yōu)缺點(diǎn),最好的辦法是了解各自使用方式的差異,考慮出它們性能的差異所在,在不同的業(yè)務(wù)場(chǎng)景中,避開(kāi)最容易造成性能瓶頸的用法。

ng-if跟ng-show/hide的區別有哪些?

第一點(diǎn)區別是,ng-if 在后面表達式為 true 的時(shí)候才創(chuàng )建這個(gè) dom 節點(diǎn),ng-show 是初始時(shí)就創(chuàng )建了,用 display:block 和 display:none 來(lái)控制顯示和不顯示。第二點(diǎn)區別是,ng-if 會(huì )(隱式地)產(chǎn)生新作用域,ng-switch 、 ng-include 等會(huì )動(dòng)態(tài)創(chuàng )建一塊界面的也是如此。

ng-repeat迭代數組的時(shí)候,如果數組中有相同值,會(huì )有什么問(wèn)題,如何解決?

會(huì )提示 Duplicates in a repeater are not allowed. 加 track by $index 可解決。當然,也可以 trace by 任何一個(gè)普通的值,只要能唯一性標識數組中的每一項即可(建立 dom 和數據之間的關(guān)聯(lián))。

ng-click中寫(xiě)的表達式,能使用JS原生對象上的方法,比如Math.max之類(lèi)的嗎?為什么?

不可以。只要是在頁(yè)面中,就不能直接調用原生的 JS 方法,因為這些并不存在于與頁(yè)面對應的 Controller 的 scope。scope 中添加了這個(gè)函數:

1
2
3
$scope.parseInt = function(x){
    return parseInt(x);
}

{{now | 'yyyy-MM-dd'}}這種表達式里面,豎線(xiàn)和后面的參數通過(guò)什么方式可以自定義?

定義方式:

1
2
3
4
5
6
app.filter('過(guò)濾器名稱(chēng)',function(){
    return function(需要過(guò)濾的對象, 過(guò)濾器參數1, 過(guò)濾器參數2, ...){
        //...做一些事情
        return 處理后的對象;
    }
});

使用方式有兩種,一種是直接在頁(yè)面里:

1
<p>{{now | date : 'yyyy-MM-dd'}}</p>

一種是在 js 里面用:

1
2
// $filter('過(guò)濾器名稱(chēng)')(需要過(guò)濾的對象, 參數1, 參數2,...)
$filter('date')(now, 'yyyy-MM-dd hh:mm:ss');

 factory和service,provider是什么關(guān)系?

factory 把 service 的方法和數據放在一個(gè)對象里,并返回這個(gè)對象;service 通過(guò)構造函數方式創(chuàng )建 service,返回一個(gè)實(shí)例化對象;provider 創(chuàng )建一個(gè)可通過(guò) config 配置的 service。從底層實(shí)現上來(lái)看,service 調用了 factory,返回其實(shí)例;factory 調用了 provider,將其定義的內容放在 $get 中返回。factory 和 service 功能類(lèi)似,只不過(guò) factory 是普通 function,可以返回任何東西(return 的都可以被訪(fǎng)問(wèn),所以那些私有變量怎么寫(xiě)你懂的);service 是構造器,可以不返回(綁定到 this 的都可以被訪(fǎng)問(wèn));provider 是加強版 factory,返回一個(gè)可配置的 factory。

詳述angular的“依賴(lài)注入”

AngularJS 是通過(guò)構造函數的參數名字來(lái)推斷依賴(lài)服務(wù)名稱(chēng)的,通過(guò) toString() 來(lái)找到這個(gè)定義的 function 對應的字符串,然后用正則解析出其中的參數(依賴(lài)項),再去依賴(lài)映射中取到對應的依賴(lài),實(shí)例化之后傳入。因為 AngularJS 的 injector 是假設函數的參數名就是依賴(lài)的名字,然后去查找依賴(lài)項,那如果像下面這樣簡(jiǎn)單注入依賴(lài),代碼壓縮后(參數被重命名了),就無(wú)法查找到依賴(lài)項了。

1
2
function myCtrl = ($scope, $http){
    ...}

所以,通常會(huì )使用下面兩種方式注入依賴(lài)(對依賴(lài)添加的順序有要求)。

數組注釋法:

1
2
3
myApp.controller('myCtrl', ['$scope''$http'function($scope, $http){
    ...
}])

顯式 $inject :

1
2
3
4
5
myApp.controller('myCtrl', myCtrl);
function myCtrl = ($scope, $http){
    ...
}
myCtrl.$inject = ['$scope''$http'];

對于一個(gè) DI 容器,必須具備三個(gè)要素:依賴(lài)項的注冊,依賴(lài)關(guān)系的聲明和對象的獲取。在 AngularJS 中,module 和 $provide 都可以提供依賴(lài)項的注冊;內置的 injector 可以獲取對象(自動(dòng)完成依賴(lài)注入);依賴(lài)關(guān)系的聲明,就是上面的那兩種方式。

html: {{currentDate()}} js: $scope.currentDate = function(){return new Date();} 這種寫(xiě)法有沒(méi)有問(wèn)題

有問(wèn)題,時(shí)間是實(shí)時(shí)變化的,然后會(huì )一直更新數據,效率低,臟數據檢查到10次之后不再繼續檢查;

解決方案:可以使用一個(gè)變量來(lái)接收函數調用

controller as 和controller 有什么區別,能解決什么問(wèn)題?

在使用controller的時(shí)候,為控制器注入windowscope,這個(gè)時(shí)候controller中的屬性與方法是屬于$scope的,而使用controllerAS的時(shí)候,可以將controller定義為Javascript的原型類(lèi),在html中直接綁定原型類(lèi)的屬性和方法

優(yōu)點(diǎn):

  • 可以使用 Javascript 的原型類(lèi), 我們可以使用更加高級的 ES6 或者 TypeScript 來(lái)編寫(xiě) Controller ;

  • 指代清晰。在嵌套scope時(shí),子scope如果想使用父scope的屬性,只需簡(jiǎn)單的使用父scope的別名引用父scope即可。

  • 避開(kāi)了所謂的 child scope 原型繼承帶來(lái)的一些問(wèn)題(原來(lái)別名ctrl就是定義在scope個(gè),controller個(gè)實(shí),JScontroller時(shí)thismodel實(shí)scope.ctrl上的。使用controller as的一大好處就是原型鏈繼承給scope帶來(lái)的問(wèn)題都不復存在了,即有效避免了在嵌套scope的情況下子scope的屬性隱藏掉父scope屬性的情況。)

  • controller的定義不依賴(lài)$scope。

  • 定義controller時(shí)不用顯式的依賴(lài)scope,?,個(gè),!!ScopeControllerPOJOPlainOldJavascriptObject,Java來(lái),Object無(wú)關(guān),。便使AngularJS,便。,,Object。調賴(lài),POJO滿(mǎn)個(gè),個(gè),個(gè)scope。

  • 防止濫用scopewatch,on,broadcast方法??赡軇倓偩陀腥讼雴?wèn)了,不依賴(lài)scopewatch個(gè)model,。沒(méi),scope能干。但很多時(shí)候在controller里watch一個(gè)model是很多余的,這樣做會(huì )明顯的降低性能。所以,當你本來(lái)就依賴(lài)scope時(shí),會(huì )調來(lái)實(shí)。使controlleras時(shí),沒(méi)賴(lài)scope,使用watch前你會(huì )稍加斟酌,沒(méi)準就思考到了別的實(shí)現方式了呢。

  • 定義route時(shí)也能用controller as。除了在DOM中顯式的指明ng-controller,還有一種情況是controller的綁定是route里定義好的,那這時(shí)能使用controller as嗎?答案是肯定的,route提供了一個(gè)controllerAs參數。這樣在模板里就可以直接使用別名home啦。

個(gè)人覺(jué)得還是偏向于使用controller as的,當然有一點(diǎn)要澄清,使用contoller as并沒(méi)有什么性能上的提升,僅僅是一種好的習慣罷了。

 

無(wú)論定義controller時(shí)有沒(méi)有直接依賴(lài)scope,DOMscope。使使controlleras,過(guò)scope的watch以及digest來(lái)實(shí)現的。

 

請簡(jiǎn)述$compile的用法?

angularjs里比較重要但又很少手動(dòng)調用的要屬compile務(wù),寫(xiě)時(shí),angularjs動(dòng),時(shí)動(dòng),個(gè)table,實(shí),,compile了。

$compile,在A(yíng)ngular中即“編譯”服務(wù),它涉及到Angular應用的“編譯”和“鏈接”兩個(gè)階段,根據從DOM樹(shù)遍歷Angular的根節點(diǎn)(ng-app)和已構造完畢的 $rootScope對象,依次解析根節點(diǎn)后代,根據多種條件查找指令,并完成每個(gè)指令相關(guān)的操作(如指令的作用域,控制器綁定以及transclude等),最終返回每個(gè)指令的鏈接函數,并將所有指令的鏈接函數合成為一個(gè)處理后的鏈接函數,返回給Angluar的bootstrap模塊,最終啟動(dòng)整個(gè)應用程序。

 

先解說(shuō)下angular中頁(yè)面處理

ng對頁(yè)面的處理過(guò)程:

  • 瀏覽器把HTML字符串解析成DOM結構

  • ng把DOM結構給$compile,返回一個(gè)link函數

  • 傳入具體的scope調用這個(gè)link函數

  • 得到處理后的DOM,這個(gè)DOM處理了指令,連接了數

 

$compile是個(gè)編譯服務(wù)。編譯服務(wù)主要是為指令編譯DOM元素。

編譯一段HTML字符串或者DOM的模板,產(chǎn)生一個(gè)將scope和模板連接到一起的函數。

$compile用法:

1
$compile(element,transclude,maxPriority);
  • element:將要被編譯和插入模板的元素或者HTML字符串

  • transclude:指令內有效的函數。Function(angular.Scope,cloneAttachFn=)

  • maxPriority:只有在指令比給定的優(yōu)先級低時(shí)應用。只影響根元素,不影響子元素

1
2
3
4
5
6
7
8
9
 .controller('MyController'function ($scope, $compile) {
                // 創(chuàng )建編譯函數
                var compileFn = $compile('<p>{{appCtrl.msg}}</p>');
                // 傳入scope,得到編譯好的dom對象(已封裝為jqlite對象)
                // 也可以用$scope.$new()創(chuàng )建繼承的作用域
                var $dom = compileFn($scope);
                // 添加到文檔中
                $dom.appendTo('body');
            })

通過(guò)compile務(wù)htmldomjqLite,個(gè),scope,就會(huì )在當前作用域進(jìn)行編譯,返回編譯好的jqLite對象,這時(shí)就可以直接添加到文檔中了(也可以先添加到文檔再編譯)。

編譯的實(shí)質(zhì)其實(shí)就是對dom對象解析,使dom對象與scope進(jìn)行耦合,通過(guò)綁定可以實(shí)現數據的更新,像Vue其實(shí)也是一樣的過(guò)程。

 

$compile解說(shuō)推薦看《Angular中$compile源碼分析

 

這篇是對angularJS的一些疑點(diǎn)回顧,文章的問(wèn)題大多是從網(wǎng)上搜集整理而來(lái),如有不妥之處或不遠被引用,請通知本人修改,謝謝!

首發(fā)于周陸軍個(gè)人網(wǎng)站,轉載注明來(lái)源:《再談angularJS數據綁定機制及背后原理—angularJS常見(jiàn)問(wèn)題總結

參考文章:

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
AngularJS自學(xué)之路(一)
AngularJS開(kāi)發(fā)指南04:核心概覽 | AngularJS中文社區
AngularJS在大型單頁(yè)面應用中的性能優(yōu)化(二)
使用超動(dòng)感HTML & JS開(kāi)發(fā)WEB應用! | AngularJS中文社區
AngularJS 數據綁定與 $digest 循環(huán) | 天碼營(yíng)
AngularJS 性能優(yōu)化
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久