Vue 2中的数据劫持
简介
在Vue.js这个前端框架中,数据劫持是一个核心概念,它使得Vue能够实时响应数据的变化并更新视图。在Vue 2中,数据劫持的实现主要依赖于JavaScript的Object.defineProperty
方法。
示例
在vue中,我们是这样构建实例的(代码中的data直接是一个对象,而不是一个函数)。
const vm = new Vue({
el: '#app',
data: {
name: 'w',
age: 18,
sex: '男',
other: {
a: 'aaa'
},
likes: ['篮球', '足球', '乒乓球']
}
});
实现Vue方法
// Vue.js
class Vue {
constructor(options) {
const { data } = options;
this.$options = options;
this.$data = data;
}
}
export default Vue;
使用Observer监听数据
// Observer.js
class Observer {
constructor(data) {
this.walk(data);
}
walk(data) {
for (const [key, value] of Object.entries(data)) {
this.defineReactive(data, key, value);
}
}
// 监听
defineReactive(target, key, value) {
Object.defineProperty(target, key, {
get() {
return value;
},
set(newValue) {
value = newValue;
}
})
}
}
export default Observer;
// Vue.js
import Observer from './Observer.js';
class Vue {
constructor(options) {
const { data } = options;
new Observer(data);
...
}
}
我们打印vm
实例,可以看到$data
中的基础类型已经被绑定了get
和set
。而引用数据类型没有被绑定get和set。
接下来处理引用类型的数据监听
// Objserver.js
class Observer {
...
walk(data) {
if (typeof data !== "object" || data == null) {
return
}
...
}
defineReactive(target, key, value) {
this.walk(value);
...
}
}
打印vm
实例,我们可以看到likes
和other
也被绑定了get
和set
。
代理机制
通过代理机制实现vm.xxx
即可直接访问vm.$data.xxx
。
// Vue.js
class Vue {
constructor(options) {
...
this.proxyData();
}
proxyData() {
for (const key in this.$data) {
Object.defineProperty(this, key, {
get() {
return this.$data[key];
},
set(newValue) {
this.$data[key] = newValue;
}
})
}
}
}
监听数组变化
我们通过vm.likes.push('羽毛球')
,发现push
的数据没有被添加get和set。
// arrayPrototype.js
import Observer from "./Observer.js";
const arrayPrototype = Object.create(Array.prototype);
['push', 'pop'].forEach(method => {
arrayPrototype[method] = function (...args) {
Array.prototype[method].apply(this, args);
new Observer(this);
}
})
export default arrayPrototype;
通过重新设置数组的原型,实现修改数组时的数据劫持。
// Observer.js
import arrayPrototype from './arrayPrototype.js';
class Observer {
...
walk(data) {
...
if (data instanceof Array) {
Object.setPrototypeOf(data, arrayPrototype)
}
...
}
...
}
通过重新设置数组的原型,我们可以看到push
的数据已经绑定了get
和set
了。
总结
本文介绍了Vue.js中对数据进行劫持的基本概念,希望对大家有所帮助。
转载自:https://juejin.cn/post/7352708237844103220