Vue响应式数据的原理设计思想
十字真理:==**数据劫持 + 发布-订阅模式== vue双向数据绑定是 通过 数据劫持 并结合 发布-订阅模式 的方法来实现的。 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变。
双向绑定流程
-
new Vue()
首先执行初始化,对data
执行响应化处理,这个过程发生Observer
中【劫持监听所有数据】 -
同时对模板执行编译,找到其中动态绑定的数据,从
data
中获取并初始化视图,这个过程发生在Compile
中【解析模板中的指令】 -
同时定义⼀个更新函数和
Watcher
,将来对应数据变化时Watcher
会调用更新函数 -
由于
data
的某个key
在⼀个视图中可能出现多次,所以每个key
都需要⼀个管家Dep
来管理多个Watcher
-
将来data中数据⼀旦发生变化,会首先找到对应的
Dep
,通知所有Watcher
执行更新函数图解:来张网图
object.defineProperty和proxy
vue | 实现方式 | 优点 | 缺点 |
---|---|---|---|
vue2 | object.defineProperty | 支持ie9 | 1.不能拦截数组,2.必须挨个遍历对象的属性才能进行拦截3.必须递归遍历对象的属性,防止对象的属性还是对象 |
vue3 | proxy | 1,直接监听对象而非属性,2.直接监听数组的变化3.拦截的方式有很多种(有13种,set,get,has)4.Proxy 返回一个新对象,可以操作新对象达到目的 | 不支持ie |
虽然Proxy和Object.defineProperty
一样都需要递归拦截属性的get,set,但是Proxy只在调用时递归,Object.defineProperty
在一开始就递归,所以Proxy性能更高。
###vue2实现双向绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue2双向数据绑定</title>
</head>
<body>
<div style="padding: 80px;width: 300px;margin: auto">
<h3>vue2双向数据绑定实现:</h3>
<hr>
<p>输入:<input type="text" id="ipt" /></p>
<p>结果:<span id="text"></span></p>
</div>
<script>
// 页面加载获取对应的两个节点
window.onload = function(){
var ipt = document.getElementById('ipt');
var text = document.getElementById('text');
// 声明一个空对象,用于数据双向绑定
var obj = {};
// 页面加载--绑定初始值,并监听--等着被修改
reactFun(obj,'asf')
function reactFun(obj,val){
// 重新定义该空对象,实现该对象的属性的监听
//Object.defineProperty它可以用来给一个对象定义一个属性或者修改一个现有的属性,并且返回这个对象。
Object.defineProperty(obj,'name',{
configurable: true,//configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除
enumerable: true,//对象是否可枚举
get: function(){
return val;
},
set: function(newVal){
console.log('set:');
// 重新赋值到上层作用域
val = newVal;
}
});
}
// 对输入框绑定输入事件
ipt.onkeyup = function(event){
// 当输入变化时,重新赋值给obj.name
// 修改对象的值
obj.name = event.target.value;
// 取得对象的值,赋值给页面
text.innerHTML = obj.name;
}
}
</script>
</body>
</html>
vue3实现数据双向绑定
Proxy是ES6
引入的一个新特性,它允许你创建一个代理对象,用于拦截对目标对象的访问。通过使用Proxy,你可以拦截目标对象上的各种操作,比如属性访问、属性赋值、函数调用等,并在这些操作发生时执行自定义的逻辑。
在Vue3
中,Proxy被用于劫持组件实例,以实现响应式数据的跟踪和更新。当你在Vue
组件中声明一个响应式的数据属性时,Vue内部会使用Proxy来追踪该属性的变化。这样,当属性的值发生变化时,Vue
能够自动检测到这个变化,并更新相关的视图。
拦截的方式有很多种 get set has apply
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue3双向数据绑定</title>
</head>
<body>
<div>
<h3>vue3双向数据绑定实现:</h3>
<hr>
<p>输入:<input type="text" id="ipt" /></p>
<p>结果:<span id="text"></span></p>
</div>
<script>
// 页面加载获取对应的两个节点
window.onload = function(){
var ipt = document.getElementById('ipt');
var text = document.getElementById('text');
// 声明一个空对象,用于数据双向绑定
var obj = {};
var obj1 = new Proxy(obj, {
// target就是第一个参数obj, receive就是返回的obj(返回的proxy对象)
get: function (target, key, receive) {
// 返回该属性值
return target[key];
},
set: function (target, key, newVal, receive) {
// 执行赋值操作
target[key] = newVal;
}
})
ipt.onkeyup = function(event){
obj1[0] = event.target.value;
text.innerHTML = obj1[0]
}
}
</script>
</body>
</html>
有问题请联系我哦 @一路向北xwq