vue源码解析之observe
2024-08-25 10:11:35
一. vue文档中有“由于 JavaScript 的限制,Vue 不能检测以下数组的变动”,是否真是由于JavaScript的限制,还是出于其他原因考虑
- 当你利用索引直接设置一个数组项时,例如:
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:
vm.items.length = newLength
第一种情况是利用索引设置一个数组项,经过试验索引是可以设置为响应式的,再去vue源码中看看是怎么实现的,代码是在core/observer/index.js中
if (Array.isArray(value)) {
if (hasProto) {
protoAugment(value, arrayMethods)
} else {
copyAugment(value, arrayMethods, arrayKeys)
}
this.observeArray(value)
} else {
this.walk(value)
} walk (obj: Object) {
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i])
}
} observeArray (items: Array<any>) {
for (let i = 0, l = items.length; i < l; i++) {
observe(items[i])
}
}
由上面代码可知源码中确实也是分开处理的,把数组遍历后对每一项进行观测
为什么会这样呢,自己猜测是因为通过索引观测太不稳定了
比如数组很多由变异操作,都会引起索引的巨大变化,比如排序、增加或者删除等
删除中间数组项,它后面的索引都会发生变化,这不仅消耗性能,而且边界情况太多,可能大大增加vue核心的代码量。
反而现在的代码最终都是按照对象去观测,处理规则一致
总结下来如果强行去实现利用索引去设置数组项可以实现,但是付出和获得不成正比,衡量下就放弃了,可以说是衡量的结果,一定程度上也可以说是数组的索引特性造成的
第二种情况,经过测试,用Object.defineProperty去重新定义length属性会报错,由此可知length属性在初始化时已经定义了,查看文档http://yanhaijing.com/es5/#367可知
length 属性拥有的初始特性是 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }.
总结可知确实因为JavaScript 限制,当修改数据长度时不能观测到
最新文章
- python 之sqlalchemy many to one
- Gradle笔记系列(二)
- [转帖]海森矩阵(Hessian matrix)
- SQLServer 维护脚本分享(07)IO
- extjs在窗体中添加搜索框
- Android 5.0新特性了解(一)----TabLayout
- Java API —— Date类
- oracle常见为题汇总,以及一个简单数据连接操作工厂
- J2EE的13个规范之(二) JDBC 及其使用
- mysql相关日志汇总
- 使用Nginx做图片服务器时候,配置之后图片访问一直是 404问题解决
- 详解 Java 中的三种代理模式
- SESSION和cookie的使用和区别
- LA 3890 Most Distant Point from the Sea(半平面交)
- jsp 中变量作用域:pageScope、requestScope、sessionScope、applicationScope
- 最值得你所关注的10个C语言开源项目
- Canny边缘检测——学习笔记
- standby_file_management 参数为manual 导致ORA-01111问题
- saltstack常用模块
- UI-基本控件的简单使用