vue2数据双向绑定的工作原理是通过 object.defineProperty() 来劫持各个属性的setter和getter,在数据变动时 发布消息给订阅者,触发相应的监听回调。现在我们就通过代码来简单实现吧
示例将通过输入框输入 与box里面内容相互绑定
<div id="app">
<input class="username" type="text" />
<input class="password" type="text" />
<div style="display: flex;" >
<span> 账号:</span><div class="box1"></div>
</div>
<div style="display: flex;" >
<span> 密码:</span><div class="box2"></div>
</div>
</div>
// An highlighted block
let dataObj = {}
// 订阅者模拟器
const Dep = {
// 存储订阅者
clientList:{},
// 监听订阅者
listen:function(key,fn){
// 判断是否含有订阅者,没有则存储订阅者,并添加订阅方法
((this.clientList[key]) || (this.clientList[key] = [])).push(fn)
},
// 当值发生改变时推送
trigger: function(){
// Array.prototype.shift.call(arguments) 取 arguments 中的第一个参数 arguments不是数组,是类数组
let key = Array.prototype.shift.call(arguments)
// 获取订阅者的方法
fns = this.clientList[key]
if(!fns || fns.length === 0) return false
for(let i=0,fn;fn=fns[i++];){
// 将this 重新绑定到使用者
fn.apply(this,arguments)
}
}
}
// 数据劫持
let dataHijack = function({data,key,selector}){
let value = '',
el = document.querySelector(selector)
Object.defineProperty(data,key,{
get: function(){
return value
},
set:function(val){
// 更改值
value = val
console.log('设置了新值');
Dep.trigger(key,val)
}
})
// 添加订阅者模式
Dep.listen(key,function(text){
el.innerHTML = text
})
}
//调用方法
dataHijack({
data:dataObj,
key:'username',
selector:'.box1'
})
dataHijack({
data:dataObj,
key:'password',
selector:'.box2'
})
// dataObj.password = '臭屁猪'
// 绑定数据
const username = document.querySelector(".username")
const password = document.querySelector(".password")
username.addEventListener("keyup",function(e){
// console.log(e.target.value);
dataObj.username = e.target.value
})
password.addEventListener("keyup",function(e){
// console.log(e.target.value);
dataObj.password = e.target.value
})
这样就完成了