昨天在項目中遇到一個問題:
文本框中輸入值只要變化就要請求接口獲取數據賦值給couponData,這樣性能不好。所以和服務器端溝通改成了服務器端一次性返回所有數據,這樣前端只要獲取一次數據然后保存在對象里面,然后當輸入值變化根據匹配規則自己來判斷。
但是輸入值變化每次請求接口獲取值賦給couponData之后是可以重新渲染DOM元素的;一次獲取保存在對象里面是不能重新渲染DOM元素的!我就查了一下原因如下:
輸入值變化每次請求接口獲取值賦給couponData之后,看一下couponData值如下(每次發請求這個$$hashkey都會變化):
我們可以看到 ng-repeat 往數組里每個元素加了一個 $$hashKey 的屬性,用於綁定DOM。這個 key 是由 Angular 內部的 nextUid() 方法生成,類似數據庫自增,但是是使用字符串。
查看 ng-repeat 的源碼可以發現,當 ng-repeat 的數組被替換時, 它默認並不會重新利用已有的 Dom 元素,而是直接將其全部刪除並重新生成新的數組 Dom 元素:
// 將上次生成的所有 dom 移除 for (key in lastBlockMap) { if (lastBlockMap.hasOwnProperty(key)) { block = lastBlockMap[key]; elementsToRemove = getBlockElements(block.clone); $animate.leave(elementsToRemove); forEach(elementsToRemove, function(element) { element[NG_REMOVED] = true; }); block.scope.$destroy(); } }
這就是每次都請求接口賦值給couponData之后是會重新生成新的 $$hashKey 值,所以會重新渲染DOM元素;所以只獲取值一次保存在對象里面不會重新渲染的原因是因為$$hashKey 沒有變化導致的,是重用DOM元素,為了解決這個問題,我用隨機數方式重新復制給$$hashkey就可以了。