问题:Vue的单项数据是如何绑定的
为了了解vue的的单向数据绑定原理,看了官方文档
,
发现Object.defineProperty是其核心,又查看了MDN文档,以下是自己参考文档和其他文章,使用原生js写出的代码,首先让代码跑起来,有个直观的感受,然后再深入解析。
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
display: flex;
justify-content: center;
align-items: center;
margin: 0;
padding: 0;
height: 100vh;
}
.main{
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
</style>
<title>用原生js实现单向数据绑定</title>
</head>
<body>
<div class="main">
<input type="text" id="model">
<div id="modelText"></div>
</div>
<script>
var model = document.querySelector("#model")
var modelText = document.querySelector("#modelText")
var defaultName = 'hello world'
var userInfo = {}
model.value = defaultName
Object.defineProperty(userInfo, 'name', {
get: function() {
return defaultName
},
set: function(newValue) {
model.value = newValue;
console.log("newValue is ===>>>", newValue)
modelText.textContent = newValue
}
})
userInfo.name = defaultName
var isEnd = true
model.addEventListener('keyup', function() {
if (isEnd) {
userInfo.name = this.value
}
}, false)
// 监听中文输入法切换
model.addEventListener('compositionstart', function() {
console.log('开始中文输入')
isEnd = false
})
model.addEventListener('compositionend', function() {
isEnd = true
console.log("结束中文输入")
})
</script>
</body>
</html>
代码解析
Object.defineProperty() 方法直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。
用法如下:
Object.definProperty(
obj, // 要在其上定义的对象
prop, // 要定义或修改的属性的名称
descriptor // 将被定义或修改的属性描述符
)
例子中通过Object.definProperty将userInfo.name的值利用get来获取值,利用set来监听值的变化。
var userInfo = {}
Object.defineProperty(userInfo, 'name', {
get: function() {
},
set: function(newValue) {
}
})
回头看Vue中的实现
- 当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
- 这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在属性被访问和修改时通知变更。
- 每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据属性记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
同时官方文档有图,更加直观的展示了数据变化过程
image
网友评论