Vue双向绑定原理解析

首先我们需要了解一下attribute和property的区别

  • attribute: 是HTML节点的属性,例如id, class, style等
  • property: 是js中对象的属性,而js中万物皆对象。对js获取的DOM节点对象来说,attributes只是这个对象的properties的其中一项

这里先贴一段代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<span id="harry" style="line-height: 32px;">&nbsp;</span><br>
		<input id="trigger" type="text">
		<script type="text/javascript">
		   let harry = document.getElementById('harry')
		   let trigger = document.getElementById('trigger')
		   let key = 'profile'  // 对象属性键名
		   let store = {}      // 辅助get取值
		   let obj = {         // 对象
			 profile: ''
		   }
		   Object.defineProperty(obj, key, {
			 set (value) {
				harry.innerText = value  // 重点:修改DOM节点视图
				trigger.value=value
				store[key] = value
			 },
			 get () {
				return store[key]
			 }
		   })
		   trigger.addEventListener('keyup', function () {
			 obj[key] = this.value
			 console.log(obj[key])
		   })
		</script>
	</body>
</html>

如图是harry的部分properties

我们再看一下身为对象属性的obj.profile的properties

再来看一下对象属性配置表你就明白Object.defineProperty方法定义的property有什么用了

名称 默认值 说明
configurable false 标识属性配置是否可更改和该属性是否可以从对象中删除
enumberable false 标识属性是否可被枚举
writable false 标识属性是否可通过赋值运算修改,不与set共存
value undefined 属性值,可以为任意js数据类型,不与set共存
set undefined 函数类型,属性被赋值时调用
get undefined 函数类型,返回值将作为属性值

上述代码中,笔者在对象属性的setter函数中修改文本节点的值,所以当obj.profile被重新赋值时,节点视图也会同步更新;然后对输入框添加事件监听(addEventListener),当用户事件触发时,输入值将被赋于obj.profile。以此方式,我们实现了数据与视图之间的“双向绑定”,这也是Vue数据与视图绑定的实现原理。

在Vue中,当我们把普通的JavaScript对象传给Vue实例的data选项时,Vue将遍历对象属性,并使用Object.defineProperty将其全部转化为getter/setter,并在组件渲染时将属性记录为依赖。之后当依赖项的setter函数被调用时,会通知watcher重新计算并更新其关联的所有组件。
由于Object.defineProperty是ES5中一个无法shim(自定义拓展)的特性,所以Vue应用无法运行在不支持Object.defineProperty的IE8及其以下版本浏览器上。


参考 刘汉伟 《Vue.js从入门到项目实战》

原文地址:https://www.cnblogs.com/Minstrel223/p/12241643.html