Vue 在響應式的處理中,對數組與對象採用了不一樣的方式,以下源碼所示:javascript
if (Array.isArray(value)) {
const augment = hasProto
? protoAugment
: copyAugment
augment(value, arrayMethods, arrayKeys)
this.observeArray(value)
} else {
this.walk(value)
}
複製代碼
當值是數組時,Vue 經過攔截數組變異方法的方式來實現響應式,此種方式有兩弊端:html
既然在單獨處理數組時,有以上弊端,那爲何不使用和純對象同樣的方式?java
修改部分源碼以下:數組
if (Array.isArray(value)) {
// const augment = hasProto
// ? protoAugment
// : copyAugment
// augment(value, arrayMethods, arrayKeys)
// this.observeArray(value)
this.walk(value)
} else {
this.walk(value)
}
複製代碼
接着,咱們主要對數組測試兩點,利用索引設置項,以及修改數組長度:app
<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] = 5 this.test.length = 10 console.log(this.test) // [5, 2, 3, 4, empty * 6] } } }) </script>
複製代碼
當點擊 button 時,能看到結果: 性能
Wait, 爲何數組裏出現了 null ?測試
當給數組設置 length 時,若是大於數組自己長度,新元素則會以 empty 填充,以下所示:ui
const arr = [1, 2, 3]
arr.length = 5
console.log(arr) // [1, 2, 3, empty * 2]
複製代碼
empty 不一樣於 undefined,在遍歷時,會被忽略:this
const arr = [1, 2, 3]
arr[5] = undefined
console.log(arr) // [1, 2, 3, empty * 2, undefined]
arr.forEach(item => console.log(item))
// 1 2 3 undefined
複製代碼
那麼問題來了,上圖中爲何出現 null?(this.test
打印出來正常,在 html 中渲染出 null)spa
爲了探究此問題,我嘗試在 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 是可使用與處理純對象的方式來處理數組的。官方解釋不這麼作的緣由是出於對性能的考慮。
爲了獲得驗證,我嘗試使用如下兩種不一樣方式:
經過二者頁面 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…