当 Vue 处理数组与处理纯对象的方式一样
處理數組方法的弊端
Vue 在響應式的處理中,對數組與對象采用了不同的方式,如下源碼所示:
if (Array.isArray(value)) {const augment = hasProto? protoAugment: copyAugmentaugment(value, arrayMethods, arrayKeys)this.observeArray(value) } else {this.walk(value) }復制代碼當值是數組時,Vue 通過攔截數組變異方法的方式來實現響應式,此種方式有兩弊端:
- 通過索引設置項,Vue 不能監測到。
- 修改數組長度時,Vue 也不能監測到。
使用與處理純對象相同的方式
既然在單獨處理數組時,有以上弊端,那為什么不使用和純對象一樣的方式?
修改部分源碼如下:
if (Array.isArray(value)) {// const augment = hasProto// ? protoAugment// : copyAugment// augment(value, arrayMethods, arrayKeys)// this.observeArray(value)this.walk(value) } else {this.walk(value) }復制代碼接著,我們主要對數組測試兩點,利用索引設置項,以及修改數組長度:
<div id="app"><div>{{ test }}</div><div>{{ test.length }}</div><button @click="someMethod">button</button> </div> <script> new Vue({el: '#app',data: {test: [1, 2, 3, 4]},methods: {someMethod () {this.test[0] = 5this.test.length = 10console.log(this.test) // [5, 2, 3, 4, empty * 6]}} }) </script> 復制代碼當點擊 button 時,能看到結果:
Wait, 為什么數組里出現了 null ?
null?empty?
當給數組設置 length 時,如果大于數組本身長度,新元素則會以 empty 填充,如下所示:
const arr = [1, 2, 3] arr.length = 5 console.log(arr) // [1, 2, 3, empty * 2] 復制代碼empty 不同于 undefined,在遍歷時,會被忽略:
const arr = [1, 2, 3] arr[5] = undefinedconsole.log(arr) // [1, 2, 3, empty * 2, undefined]arr.forEach(item => console.log(item))// 1 2 3 undefined 復制代碼那么問題來了,上圖中為什么出現 null?(this.test 打印出來正常,在 html 中渲染出 null)
為了探究此問題,我嘗試在 html 中輸出一個數組變量:
const arr = [1, 2, 3] document.write(arr) 復制代碼可是事與愿違:
我好像得到了字符串。
換個對象試試:
const obj = { a: 1 } document.write(obj) 復制代碼結果:
輸出的結果,好像被 toString() 了?
const obj = { a: 1 } console.log(obj.toString()) // [object Object] 復制代碼也就是說,當你嘗試在頁面輸出一個變量時,JavaScript 會自動調用 toString() 方法。
既然這樣,為了讓頁面輸出一個變量,需要把變量序列化:
const arr = [1, 2, 3] arr.length = 6 document.write(JSON.stringify(arr)) 復制代碼得到結果:
[1, 2, 3, null, null, null] 復制代碼數組成員里的 empty 在經過 JSON.stringify 后,轉化成了 null 。
大數組下的性能問題
從例子中可以看出,其實 Vue 是可以使用與處理純對象的方式來處理數組的。官方解釋不這么做的原因是出于對性能的考慮。
為了得到驗證,我嘗試使用以下兩種不同方式:
- Vue 單獨處理數組的方式;
- 和處理純對象相同的方式。
通過兩者頁面 Load 時間,來對比性能差異。
測試代碼:
<div id="app"><div>{{ test }}</div> </div> <script> const arr = new Array(100000) new Vue({el: '#app',data: {test: arr} }) </script> 復制代碼當使用 Vue 單獨處理數組的方式時:
當使用與處理純對象相同的方式時:
可見性能上,前者還是好很多。畢竟遍歷很長的數組,確實是一件很耗性能的事。
我的博客即將同步至騰訊云+社區,邀請大家一同入駐:cloud.tencent.com/developer/s…
總結
以上是生活随笔為你收集整理的当 Vue 处理数组与处理纯对象的方式一样的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql 非交互查询 存入execl
- 下一篇: CentOS_6.5配置iptables