vue的双向绑定的原理是什么()
vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()或者Proxy来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
Vue2.0整体思路
核心:通过Object.defineProperty()来实现对属性的劫持,达到监听数据变动的目的
Vue遍历data对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter,在属性被访问和修改时通知变更。
通过如下代码实现对属性的监听:
var data = https://www.it610.com/article/{name:'Pat'};
observe(data);
data.name = 'PatWu';
// 哈哈哈,监听到值变化了 kindeng --> dmq
function observe(data) {
if (!data || typeof data !== 'object') { return;
} // 遍历所有属性 Object.keys(data).forEach(function(key) {
defineReactive(data, key, data[key]);
});
};
function defineReactive(data, key, val) {
observe(val);
// 递归处理子属性
Object.defineProperty(data, key, {
enumerable: true,
configurable: false,
get: function() {
console.log('监听到了取值: ', val);
return val;
}, set: function(newVal) {
console.log('监听到了值变化: ', val, ' --> ', newVal);
val = newVal;
} });
}
在渲染过程中会对 vm 上的数据访问,这个时候会触发了据对象的 getter。那么每个对象值的 getter 都持有一个 dep,在触发 getter 的时候会调用 dep.depend() 方法,
从而实现依赖的收集:
// ...省略
function defineReactive(data, key, val) {
observe(val);
var dep = new Dep();
// 实例化依赖收集对象
Object.defineProperty(data, key, {
get: function() {
// 依赖收集 dep.depend();
// Dep.target.addDep(this) return val;
} // ... 省略 });
}
Dep.target 渲染过程中已经被赋值为渲染 watcher,那么就执行到 addDep 方法, 接着把当前的 watcher 订阅到这个数据持有的 dep 的 subs 中,
这个目的是为后续数据变化时候能通知到哪些 subs 做准备。
// watcher.js
function addDep(dep) {
// ...省略 dep.addSub(this)}
收集依赖并监听到变化之后就是怎么通知订阅者了,数据变动触发数据对象的setter,setter中会执行dep.notify(),再调用订阅者的update方法实现数据更新渲染。
// ... 省略
function defineReactive(data, key, val) {
observe(val);
var dep = new Dep();
// 实例化依赖收集对象
Object.defineProperty(data, key, {
// ... 省略 set: function(newVal) {
if (val === newVal) return;
console.log('监听到了值变化: ', val, ' --> ', newVal);
val = newVal;
dep.notify();
// 通知所有订阅者
} });
}
function Dep() {
this.subs = [];
}
Dep.prototype = { addSub: function(sub) {
this.subs.push(sub);
}, notify: function() {
this.subs.forEach(function(sub) {
sub.update();
// 触发更新渲染
});
}};
Vue3.0实现方式
Vue 3.0与Vue 2.0的区别仅是数据劫持的方式由Object.defineProperty更改为Proxy代理,其他代码不变。
function observer(data) {
const that = this;
for(var key in data){ that.deps[key] = [];
//初始化所有订阅者对象{msg: [订阅者], info: []} } let handler = { get(target, property) {
return target[property];
}, set(target, key, value) {
let res = Reflect.set(target, key, value);
var watchers = that.deps[key];
watchers.map(item => {
item.update();
});
return res;
} } // 通过Proxy实现对数据的劫持 this.$data = https://www.it610.com/article/new Proxy(data, handler);
}
【vue的双向绑定的原理是什么()】Object.defineProperty 和 Proxy的优缺点:
1.Object.defineProperty的缺点
不能监听数组:因为数组没有getter和setter,因为数组长度不确定,如果太长性能负担太大
只能监听属性,而不是整个对象,需要遍历循环属性
只能监听属性变化,不能监听属性的删减
2.proxy的好处
可以监听数组
监听整个对象不是属性
13种来截方法,强大很多
返回新对象而不是直接修改原对象;
3.proxy的缺点
兼容性不好,而且无法用polyfill磨平;
推荐阅读
- Python#常用的模块和简单用法
- 8个Python高效数据分析的技巧
- base64图片大小的计算与压缩
- verilog实战|verilog实现时钟的偶数与奇数分频
- 并发CAS机制你真的理解了嘛((深入到操作系统分析))
- vue社交软件分享
- 数据分析也能Freestyle | 不一样的Smartbi Insight
- 线性代数|矩阵的坐标系变换
- 投稿|被社会毒打的专科生,逆袭后年入百万
- 利用ArcGIS提取高光谱图像每个像素的光谱信息,再利用matlab显示每个像素的光谱信息