Vue2.x响应式原理
在Vue2.x
中响应式的核心是通过Object.defineProperty
来完成的,但是该属性无法降级(shim)处理,所以Vue
不支持IE8
以及更低版本的浏览器。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- <input type="text" v-model="name"> -->
<p v-text="name"></p>
<p v-text="age"></p>
<p v-text="name"></p>
</div>
<script>
let data = {
name: '李白',
age: 18
}
</script>
<script src="v-text.js"></script>
<!-- <script src="v-model.js"></script> -->
<!-- <script src="v-model-观察者.js"></script> -->
</body>
</html>
v-text.js
//枚举data中的属性,循环data中的所有属性
Object.keys(data).forEach(key => {
/**
* 为每个属性添加属性监听事件
* data 要监视的对象
* key 监视对象中的属性
* data[key] 监视对象中的属性值
*/
defineReactiveProperty(data, key, data[key])
})
function defineReactiveProperty(data, key, value) {
/**
* Object.defineProperty
* 第一个参数是要定义属性的对象
* 第二个参数是要定义或修改的属性的名称
* 第三个参数是要定义或修改的属性描述符
*/
Object.defineProperty(data, key, {
//读取属性时
get() {
return value
},
//修改或定义属性时
set(newValue) {
//newValue为定义的新值
value = newValue
compile()
}
})
}
//实现自定义响应式数据
function compile() {
//获取页面绑定的根元素
let app = document.querySelector('#app')
//获取根元素下的所有子节点
const nodes = app.childNodes
//循环遍历子节点
nodes.forEach(node => {
//判断是否为标签
if (node.nodeType === 1) {
//attributes 属性返回指定节点的属性集合,类型为伪数组
const attrs = node.attributes
//Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组
Array.from(attrs).forEach(attr => {
//筛选属性为"v-text"的标签,并修改其值
if (attr.nodeName === "v-text") {
node.innerHTML = data[attr.nodeValue]
}
})
}
})
}
compile()
数据响应式:数据模型仅仅是普通的JavaScript
对象,而当我们修改数据时,视图会进行更新,避免了频繁的DOM
操作,提高开发效率,这与Jquery
不一样,Jquery
是频繁的操作Dom