响应式:无需操作DOM,通过数据修改触发对应的页面修改
vue使用了Proxy 代理函数,Proxy 是一个构造函数,进行变量劫持定义,劫持整个对象的变化,弥补 defineProperty 函数的不足。
// 基于构造函数创建一个被劫持的代理对象,对对象的所有操作进行拦截控制
new Proxy(target,{
// target 目标对象
get( target,propName ){
// 对象任何取值劫持函数,通过return对对应访问属性进行取值返回
}
set( target,propName,newValue ){
// 对象任何赋值劫持函数
//target 被代理的对象
//propName 当前正在操作的属性
//newValue 赋值时的新数据
}
})
<div id="app">
<h1 v-text="msg"></h1>
<input type="text" oninput="setMsg(this.value)">
<hr>
<h1 v-text="info"></h1>
<input type="text" oninput="setInfo(this.value)">
</div>
vue3响应式原理,简单实现完整代码
let data = {
msg:"msg",
info:"info",
}
// ----- 响应式 ----->
//将没有劫持的数据对象赋值作为中转数据对象使用
let _data = data;
//如果是vue2需要将对象数据重新赋值为{}
data = new Proxy({},{
get(target,propName){
return target[ propName ]
},
set(target,propName,newValue){
target[ propName ] = newValue
}
})
let appDom = document.querySelector("#app")
// 循环对象获取所有对象属性
for (let key in _data) {
let doms = appDom.querySelectorAll( `[v-text='${key}']` )
doms.forEach(function(d){
d.textContent = _data[key]
})
Object.defineProperty(data,key,{
enumerable:true,
configurable:true,
get(){
return _data[ key ]
},
set(nv){
data[ key ] = nv;
// 对当前属性对应的DOM元素进行更新
doms.forEach(function(d){
d.textContent = nv
})
}
})
}
// ----- 响应式 ----->
function setMsg(v){
data.msg = v;
}
function setInfo(v){
data.info = v;
}