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
出來的樣子長這樣
好好觀察一下watch和watchCollection的行為,可以發現watch是監聽不到陣列的變化的,所以,如果你要監聽的是一個陣列的話,請用watchCollection代替watch.
以上兩點就是今天要說的優化,當然$watch還有很多其他內容,感興趣的小夥伴可以繼續研究一下。