Object.defineProperty() 基础知识请看上一篇文章:理解Object.defineProperty()
在上篇文章最后我提到了vue.js 是通过Object.defineProperty() 方法来实现双向数据绑定的
,双向数据绑定原理我准备在下一篇Vue.js 双向数据绑定原理剖析
再细说,这一篇先借助一个小例子自己来实现双向数据绑定。
那么双向数据绑定到底是什么呢?
- 当数据发生变化的时候,使用到数据的地方同步变化,即模型到视图(model => view)
- 当使用到数据的地方发生改变的时候,数据也同步变化,即视图到模型(view => model)
因此监听数据及视图的变化是实现双向数据绑定的核心,那么如何监听数据的变化呢?我在理解Object.defineProperty()提到Object.defineProperty()
方法里的get()
和set()
可以分别监听数据的获取和设置。话不多说,直接上代码。
let aVal = 1
let obj = {}
Object.defineProperty(obj, 'a', {
set(newVal) {
console.log('设置a')
aVal = newVal
},
get() {
console.log('获取a')
return aVal
}
})
双向绑定.gif
代码分析:
当获取obj.a
时,get方法被调用,执行get()里的代码输出‘获取a’并返回aVal的值作为obj.a
的值;当设置obj.a
为100时,set方法被调用,执行set()里的代码输出'设置 a'并修改aVal的值为100,这样我们就做到了监控obj.a
的存取。
其实在set()方法里我们不止可以进行打印操作,还可以进行其他的操作,比如修改页面元素显示的值,这是不是就实现了从模型到视图的同步?
模型-->视图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<input type="text" id="my-input" value="看我变变变">
<h3 id="my-title">看我变变变</h3>
</head>
<body>
<script>
let message = ''
let obj = {}
Object.defineProperty(obj, 'show', {
set(newVal) {
console.log('设置show')
message = newVal
document.querySelector('#my-input').value = newVal
document.querySelector('#my-title').innerText = newVal
},
get() {
console.log('获取show')
return message
}
})
</script>
</body>
</html>
数据到视图.gif
从上面的执行结果可以看到,已经实现了监控数据(模型)改变,视图同步跟着变化,要实现双向绑定,还需要做到监控视图改变,让数据(模型)同步变化。
视图-->模型
以id为‘#my-input’ 的input框为例,需求是文本框输入内容一旦发生变化,同步更新obj.show
的值。具体做法是:监听文本框的“ keyup” 事件。因为每当文本框的值发生改变就会触发keyup事件,那么我们只需要在keyup事件里面修改obj.show
的值就好了,这就实现了视图到模型(view => model)的同步。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<input type="text" id="my-input" value="看我变变变">
<h3 id="my-title">看我变变变</h3>
</head>
<body>
<script>
let message = ''
let obj = {}
Object.defineProperty(obj, 'show', {
set(newVal) {
console.log('设置show')
message = newVal
document.querySelector('#my-input').value = newVal
document.querySelector('#my-title').innerText = newVal
},
get() {
console.log('获取show')
return message
}
})
document.querySelector('#my-input').addEventListener('keyup', (e) => {
obj.show = e.target.value
console.log('视图更新,同步数据')
})
</script>
</body>
</html>
双向数据绑定.gif
这样就实现了简单的双向数据绑定了,是不是很简单呢?下一篇:Vue.js 双向数据绑定原理剖析
文中有不足或者读者有疑问或更好的见解,欢迎留言讨论。
如果觉得该篇文章对您有帮助,别忘了留下您的足迹,点个赞❤噢
网友评论