Vue 数据响应
Vue数据响应原理 :
1、通过 Object.defineProperty()方法改为 get set 方式获取 state 状态
2、处理 state 与节点之间的映射关系
3、更新 state 的数据到页面节点上
html 部分
<div id="root"> // el 挂载点 data-on i-module ==》 数据绑定
<h1 data-on='a'></h1>
<h1 data-on='a'></h1>
<input type="text" name="" id="" i-module='a'>
<h1 data-on='conut'></h1>
<input type="text" name="" id="" i-module='conut'>
<h1 data-on='msg'></h1>
<input type="text" name="" id="" i-module='msg'>
</div>
js部分
1、 创建实例化对象
let App = new Vue({
el: '#root',
data() {
return {
a: 1,
conut: 2,
msg: 'hello'
}
}
})
2、state 的处理:==> 状态 初始化和更新并渲染到页面(处理数据)
class Vue {
constructor({ el, data } = {}) {
this.$el = document.querySelector(el);
this.$data = data();
this.init()
}
init() {
this.$ob = this.createObserver() // 用来 处理 state 和 节点之间的映射 的方法
this.defineProperty()
}
createObserver() {
const that = this;
// 用来维护 state 和 view
return {
// 处理 state 和 节点之间的映射
swtcher: {
// 映射关系列表
maps: {},
// 新增映射关系(往 maps中添加状态和 cb()方法)
add(k, cb) {
if (this.maps[k]) {
this.maps[k].push(cb)
return;
}
this.maps[k] = [cb]
}
},
// 订阅
subscribe(k) {
// 获取挂载点下有 data-on 属性的节点
that.$el.querySelectorAll(`[data-on=${k}]`).forEach(item => {
// 容器 通过 item.innerHTML = text 给值
const cb = text => item.innerHTML = text
this.swtcher.add(k, cb)
})
that.$el.querySelectorAll(`[i-module=${k}]`).forEach(item => {
// input 等 通过 item.value = text 给值
const cb = text => item.value = text
item.addEventListener('input', e => {
console.log(that[k]);
console.log(e.target.value);
that[k] = e.target.value
})
this.swtcher.add(k, cb)
})
this.emit(k) // 调用 映射关系列表(maps)中的cd 方法更新节点的状态
},
// 更新
emit(k) {
this.swtcher.maps[k].forEach(cb => cb(that[k]))
}
}
}
// 1、通过 get set 获取和更改状态
defineProperty() {
for (let k in this.$data) {
Object.defineProperty(this, k, {
enumerable: true,
configurable: true,
get: () => this.$data[k],
set(value) {
if (value !== this.$data[k]) {
this.$data[k] = value
// 更改 state 触发 set()调用然后 更新 view
this.$ob.emit(k)
}
}
})
// 订阅 (state)
this.$ob.subscribe(k)
}
}
}