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…