数据响应式原理
- vue实现数据响应式的原理就是利用了Object.defineProperty(),重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现。
- 但是,vue3.0版本采用的是ES6的Proxy对象实现。
贴代码
<!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>Vue数据响应式原理</title>
</head>
<body>
<script>
//1.首先根据上图实现整体的一个架构(包括MVVM类或者VUE类,Watcher类)
//2.然后
//3.最后实现V-M, 当文本框输入文本的时候,由文本事件触发更新模型中的数据,同时也更新相对应的视图
class Vue {
constructor(options) {
this.options = options
this.$data = options.data //获取数据
this.$el = document.querySelector(options.el) //#app 获取app对象
this._directive = {} //容器,存放订阅者的 ; 选择如下第二种,局部渲染
//方式一:{订阅者1,订阅者2,订阅者3,订阅者4} | 全部渲染
//方式二:{myText:[订阅者1,订阅者2],myBox:[订阅者3,订阅者4]} | 局部渲染
this.Observer(this.$data) //数据
this.Complite(this.$el) //元素
}
//劫持数据
Observer(data) {
for (let key in data) {
this._directive[key] = []
//此时要进行数据的劫持,需要修改data属性的get和set
let val = data[key]
let watch = this._directive[key] //return array
Object.defineProperty(this.$data, key, {
get() {
return val;
},
set(newVal) {
if (newVal !== val) {
val = newVal
watch.forEach(element => {
element.update()
});
}
}
})
}
console.log(this._directive)
}
//解析指令
//找指令干嘛 ?? 依赖搜集! 好去订阅 data 里面的属性 -> 进行数据更新
Complite(el) {
let nodes = el.children //是app下的所有dom对象
for (let i = 0; i < nodes.length; i++) {
let node = nodes[i]
// 递归查询所有dom元素 - 获取指令
if (node.children.length > 0) {
this.Complite(node)
}
if (node.hasAttribute('v-text')) {
let attrVal = node.getAttribute('v-text') //myText
//node 当前元素对象
//attrVal 当前元素对象 指令的值
this._directive[attrVal].push(new Watcher(node, this, attrVal, "innerHTML"))
}
if (node.hasAttribute('v-model')) {
let attrVal = node.getAttribute('v-model') //myText
//node 当前元素对象
//attrVal 当前元素对象 指令的值
this._directive[attrVal].push(new Watcher(node, this, attrVal, "value"))
let self = this
//箭头函数 this 就是指的vue 不需要重新引用
node.addEventListener("input", () => {
this.$data[attrVal] = node.value //给数据赋值
})
}
}
console.log(this._directive)
}
}
//订阅者
class Watcher {
constructor(el, vm, exp, attr) {
this.el = el //元素对象
this.vm = vm
this.exp = exp
this.attr = attr
this.update()
}
//主要功能 更新视图
update() {
this.el[this.attr] = this.vm.$data[this.exp]
//更新元素 div 数据的操作
//node.innerHtml = this.vue.$data['myText]
//更新 input 数据的操作
//node[value] = this.vue.$data['myText]
}
}
</script>
<div>
<div id="app">
<h1>数据响应式</h1>
<div>
<div v-text='myText'></div>
<div v-text='myBox'></div>
<input type="text" v-model="myText" />
<input type="text" v-model="myBox" />
</div>
</div>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
myText: "大吉大利 , 今晚吃鸡",
myBox: "我是一个阿木木"
}
})
</script>
</body>
</html>
网友评论