响应式属性 VS 非响应式属性
-
响应式
- 当Vue组件的实例初始化的时候已有的数据就是响应式数据
- 通过Object.defineProperty代理实例this身上的
- 响应式属性的值发生改变会触发视图更新
-
非响应式
- 当Vue组件的实例初始化的时候没有,后期添加的属性
- 没有通过Object.defineProperty代理实例this身上的
- 非响应式属性的值发生改变不会触发视图更新
-
如何设置响应式属性
- this.$set(target, propertyName/index, value)
- Vue.set(target, propertyName/index, value)
-
数据劫持代理代码实现,在线js运行:https://www.sojson.com/runjs.html
- 单一数据对象的代理操作,只监控age值
let data = { username: "Vane", }; let age = 42; Object.defineProperty(data, "age", { get() { console.log("get()"); return age; }, }); console.log(data.age); data.age = 12; console.log(data.age); // age 值还是原值 console.log(data); // 只有 get 没有 set设值
- 设置修改原对象值会造成死循环
let data = { username: "Vane", }; let age = 42; Object.defineProperty(data, "age", { get() { console.log("get()"); return age; }, set(newValue) { console.log("set()", newValue); data.age = newValue; // 死循环 }, }); console.log(data.age); data.age = 12; console.log(data.age); // age 值还是原值 console.log(data); // 只有 get 没有 set设值
- 设置一个中间新值来进行操作,这样修改的就不是原值,以处理死循环状态
- 打印出的对象内容就包含set/get方法,但需要注意打印的是myAge不再是age
console.log(data.age); data.age = 12; console.log(data); // age 值还是原值 console.log(data.myAge); // 打印的值不再是data.age而是dage.myAge
- 循环多值进行动态值的监控,利用中括号进行动态值的获取,但修改原值仍旧会死循环
- 声明一个中间空对象来进行中转,第一个参数为中间空对象参数,而后续操作处理的则是新建的中转对象
let data = { username: 'Vane', age: 42 } // 组件实例 let myThis = {} // myThis.xxx = 123 // myThis.xxx = 234 for(let key in data){ // console.log(key, data[key]) // Object.defineProperty(target, newKey, {}) 给指定的对象添加扩展属性 Object.defineProperty(myThis, [key], { get(){ return data[key] }, // 监视扩展属性 set(newValue){ // 更新data中的数据 data[key] = newValue // 调用update更新视图 } }) } console.log(myThis) myThis.username = 'chinavane' console.log(myThis.username)