優化Angularjs的$watch方法

北辰狼月發表於2018-06-29

Angularjs的$watch相信大家都知道,而且也經常使用,甚至,你還在為它的某些行為感到惱火。比如,一進入頁面,它就會呼叫一次,我明明希望它在我初始化之後,值再次變動才呼叫。這種行為給我們帶來許多麻煩。而我們今天就是要優化$watch的寫法,來解決這些問題。

一.推薦寫法:

$scope.$watch('xxx',function(newVal,oldVal){
if(newVal === oldVal || oldVal==undefined){
  //不執行程式碼
}else{
  //執行你的程式碼
}})

為什麼這麼寫?聽我慢慢道來。

1.newVal===oldVal

首先,我們做一個測試。

$scope.$watch('name',function(newVal,oldVal){
    console.log('oldVal',oldVal)        //undefined
    console.log('newVal',newVal)        //undefined
    if(newVal === oldVal || oldVal==undefined){
    //不執行程式碼
    }else{
  //執行你的程式碼
    }
})

我們監聽name的改變,一開始進來,沒有初始化時,都為undefined。

然後,我們先定義name

$scope.name="張三";
$scope.$watch('name',function(newVal,oldVal){
    console.log('oldVal',oldVal)        //張三
    console.log('newVal',newVal)        //張三
    if(newVal === oldVal || oldVal==undefined){
    //不執行程式碼
    }else{
  //執行你的程式碼
}})

可以看到,一開始進來就都是張三。
由此可知,當監聽器函式初始化時,newVal和oldVal總是相等的,所以,此時我們可以判斷兩個值是否相等,來執行我們想要的操作。

2.oldVal==undefined

為什麼要判斷oldVal==undefined?因為,當我們給name賦值的時候,會有一個undefinde變為有值的過程。所以當你不想在第一次賦值時,就執行方法,這麼幹就對了。
我們給name的賦值套一個timeout,模仿非同步呼叫,在實際專案中,我們的name通常都是從介面獲取的。

$timeout(function(){
$scope.name="張三";
},500)

然後,你再觀察一下watch

$scope.$watch('name',function(newVal,oldVal){
    console.log('oldVal',oldVal)        //undefined
    console.log('newVal',newVal)        //張三
    if(newVal === oldVal || oldVal==undefined){
    //不執行程式碼
    }else{
  //執行你的程式碼
}})

以上就是watch需要注意的一些事項。然後,我們接下來討論的是如何監聽陣列的變化,這就要用到另一個監聽方法,$watchCollection。

二.watchCollection

大家,可以執行以下程式碼,
https://codepen.io/hanwolfxue/pen/XYyVYv?editors=1010
出來的樣子長這樣
優化Angularjs的$watch方法

好好觀察一下watch和watchCollection的行為,可以發現watch是監聽不到陣列的變化的,所以,如果你要監聽的是一個陣列的話,請用watchCollection代替watch.

以上兩點就是今天要說的優化,當然$watch還有很多其他內容,感興趣的小夥伴可以繼續研究一下。

相關文章