简单实现Vue响应式依赖收集和更新的派发
创建一个dep类添加依赖-和触发更新依赖
class dep {
constructor() {
this.subs = new Set()
}
depend (sub) {
this.subs.add(sub)
}
notify () {
this.subs.forEach(sub => sub.update())
}
}
创建一个watcher类上面有update方法更新自己
class Watcher {
constructor(cb) {
this.cb = cb
}
update () {
this.cb()
console.log('更新', this.cb)
}
}
更新页面上的dom元素数据进行双向绑定
html元素
<div id="app"></div>
<input type="text" id="input" oninput="inputVal(event)" />
双向绑定更新input输入值-以及目标元素值插入修改
var dom = document.getElementById('app')
var input = document.getElementById('input')
function inputVal (e) {
let val = e.target.value
obj.a = val
}
function updateComponet (el, value) {
el.innerHTML = value
}
把对象各个属性值变成响应式使用observe方法
内部响应式的时候使用dep类收集了依赖
function observe (target) {
var deps = new dep()
deps.depend(real)
Object.keys(target).forEach(key => {
let defaultValue = target[key]
Object.defineProperty(target, key, {
get () {
return defaultValue
},
set (newVal) {
// target[key] = newVal
defaultValue = newVal
deps.notify()
// if(newVal === target[key]) return
}
})
})
}
observe(obj)
需要有一个更新组件目标的方法传入watcher实例
class Watcher {
constructor(cb) {
this.cb = cb
}
update () {
this.cb()
console.log('更新', this.cb)
}
}
var real = new Watcher(() => {
updateComponet(dom, obj.a)
})
完整源码实现
<!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"></div>
<input type="text" id="input" oninput="inputVal(event)" />
</body>
<script>
var dom = document.getElementById('app')
var input = document.getElementById('input')
var obj = {
a: '123'
}
function inputVal (e) {
let val = e.target.value
obj.a = val
}
function updateComponet (el, value) {
el.innerHTML = value
}
class dep {
constructor() {
this.subs = new Set()
}
depend (sub) {
this.subs.add(sub)
}
notify () {
this.subs.forEach(sub => sub.update())
}
}
class Watcher {
constructor(cb) {
this.cb = cb
}
update () {
this.cb()
console.log('更新', this.cb)
}
}
var real = new Watcher(() => {
updateComponet(dom, obj.a)
})
updateComponet(dom, obj.a)
function observe (target) {
var deps = new dep()
deps.depend(real)
Object.keys(target).forEach(key => {
let defaultValue = target[key]
Object.defineProperty(target, key, {
get () {
return defaultValue
},
set (newVal) {
defaultValue = newVal
deps.notify()
// if(newVal === target[key]) return
}
})
})
}
input.value = obj.a
observe(obj)
</script>
<style>
#app {
width: 100px;
height: 100px;
background: green;
}
</style>
</html>