当 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