前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >当 Vue 处理数组与处理纯对象的方式一样

当 Vue 处理数组与处理纯对象的方式一样

作者头像
三毛
发布2018-08-30 11:01:44
9440
发布2018-08-30 11:01:44
举报

处理数组方法的弊端

Vue 在响应式的处理中,对数组与对象采用了不同的方式,如下源码所示:

if (Array.isArray(value)) {
  const augment = hasProto
    ? protoAugment
    : copyAugment
  augment(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] = 5
      this.test.length = 10
      console.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] = 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)

为了探究此问题,我尝试在 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 单独处理数组的方式时:

当使用与处理纯对象相同的方式时:

可见性能上,前者还是好很多。毕竟遍历很长的数组,确实是一件很耗性能的事。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年08月06日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 处理数组方法的弊端
  • 使用与处理纯对象相同的方式
    • null?empty?
    • 大数组下的性能问题
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档