实现数据双向绑定
vue2.0 中使用对象的属性描述符中的get与set方法来实现,当数据发生改变时可以触发相应事件。
下面是我自己手动实现一个数据的双向绑定,效果如下图
定义基础的变量
// 定义
let x; // 我们用x来存储需要改变的值
let el = document.getElementById('x-input') // 输入框
let el2 = document.getElementById('x-value') // 显示
let active; // 用来暂存当x改变时触发的函数
事件注册对象与依赖收集
let onXChange = cb => {
active = cb
active()
active = null
}
// 依赖收集
function Dep() {
this.deps = new Set() // 收集依赖
}
// 收集active
Dep.prototype.depend = function () {
if (active) this.deps.add(active)
}
// 触发依赖的方法
Dep.prototype.notify = function(val) {
this.deps.forEach(dep => dep(val))
}
代理函数
// 属性代理
let ref = function (initVal) {
let val = initVal;
let dep = new Dep();
return Object.defineProperty({}, 'value', {
get() {
dep.depend() // 触发get时将active放入依赖中
return val
},
set(newVal) {
val = newVal // 触发set时将值赋值给val
dep.notify(newVal) // 触发事件函数
}
})
}
调用
x = ref(el.value) // 创建依赖对象,当x.value改变是会触发onXChange注册的方法
onXChange(function(val) {
el2.innerText = x.value
})
el.oninput = function(e) {
x.value = e.target.value
}
下面是html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<input type="text" value="123" name="" id="x-input">
<div id="x-value"></div>
</body>
<script src="./index.js"></script>
</html>