vue的数据来源包括
data,computed,自定义options(vm.$options),实例外(export default外)
在vue组件中data内函数返回的对象默认是响应式的,这种响应式被用在模板更新、watch变更、computed依赖
此外还有一种场景,数据本身并不需要响应式,多见于 常量 或者一些第三方库,这里就总结下添加非响应式数据的几种方式
避免把数据挂载到data内函数返回的对象上
1. 将数据定义在export default之外
1 | const bigData = { |
- 不能在模板内使用
- 其中一个实例对象的内改变数据,另一个对象内的数据也会被改变
- 实质是定义在组件这个类上面的,是类的内部变量,被所有实例对象共享
应用场景:不需要在模板内使用的常量、不变配置项等
2. 将数据定义在组件的自定义属性中
1 | export default { |
- 弊端在于数据的定义被分在了2个地方,添加的自定义属性对不了解的人会产生误解,使用时也会增加调用链
- 如果数据更改,需要手动调用this.$forceUpdate()才能使模板更新
利用Vue无法检测对象属性的添加来实现
受现代 JavaScript 的限制 (而且 Object.observe 也已经被废弃),Vue 无法检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化,所以属性必须在 data 对象上存在才能让 Vue 将它转换为响应式的
3. 在created或者mounted中使用 this.bigData
待实例完成初始化observe后,加入属性
1 | export default { |
- 同样的,数据的定义被分在了2个地方
剖析observe函数来寻找办法
1 | function initData (vm: Component) { |
4. 使用Object.preventExtensions和Object.seal
Object.isExtensible(value)返回为false
preventExtensions
1 | export default { |
Object.freeze()
1 | let a = { prop: 1, prop2: 2 } // undefined |
当bigData值改变时,都需要重新调用一次
1 | updateBigData (newBigData) { |
这种写法bigData属性是响应式的,值改变后模板会自动更新;当然如果是bigData某个属性改变,仍然需要手动调用this.$forceUpdate()
5. 使属性不可枚举
使挂载的数据key不在Object.keys(obj)返回的数组中
1 | export default { |
整体对比

参考
Object.freeze() - JavaScript | MDN
