教程来源于黑马的柴柴老师:https://cp_fe.gitee.io/course-advance/#/
现在还没时间完善步骤,先把代码贴上
<!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>手写发布订阅</title>
</head>
<body>
<div id="app">
<p v-text="name"></p>
<p v-text="age"></p>
<p v-text="name"></p>
</div>
<script>
let data = {
name: '区泽熙',
age: 22,
height: 176
}
// 遍历每一个属性
Object.keys(data).forEach((key)=>{
// key 属性名
// data[key] 属性值
// data 源对象
defineReactive(data,key,data[key])
})
function defineReactive(data,key,value){
Object.defineProperty(data,key,{
get(){
return value
},
set(newValue){
// 数据发生变化,操作dom进行更新
if(newValue === value) return
value = newValue
// 再次编译要放到新值已经变化之后只更新当前的key
dep.trigger(key)
console.log(dep)
}
})
}
// 增加dep对象,用来收集依赖和触发依赖
const dep = {
map: Object.create(null),
// 收集
collect(dataProp, updateFn){
if(!this.map[dataProp]) this.map[dataProp] = []
this.map[dataProp].push(updateFn)
},
// 触发
trigger(dataProp){
this.map[dataProp] && this.map[dataProp].forEach(updateFn => updateFn())
}
}
// 编译函数
function compile(){
let app = document.getElementById('app')
// 拿到app下所有的子元素
const nodes = app.childNodes // [text, p, text, p, text, p, text]
// 遍历所有的子元素
nodes.forEach(node => {
// nodeType为1是元素节点,3是文本结点
if(node.nodeType === 1){
const attrs = node.attributes
// 遍历所有的attributes找到 v-text
Array.from(attrs).forEach(attr => {
const dirName = attr.nodeName
const dataProp = attr.nodeValue
console.log(dirName,dataProp)
if(dirName === 'v-text'){
console.log(`更新了${dirName}指令,需要更新的属性为${dataProp}`);
node.innerText = data[dataProp]
// 收集更新函数
dep.collect(dataProp,()=>{
node.innerText = data[dataProp]
})
}
})
}
})
}
compile()
</script>
</body>
</html>