<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div>
{{a.b}}
</div>
<div>
{{c}}
</div>
</div>
<script>
// 判断是不是对象类型
function isObj(x){
if(Object.prototype.toString.call(x) == '[object Object]'){
return true
}
}
function Vue(options){
this._data = options.data
observe(this._data)
// 数据代理
for(let key in this._data){
Object.defineProperty(this,key,{
get(){
return this._data[key]
},
set(newVal){
this._data[key] = newVal
}
})
}
// 模板编译
compile(options.el,this)
}
function observe(data){
let dep = new Dep()
for(let key in data){
let val = data[key]
Object.defineProperty(data,key,{
get(){
if(Dep.target){
dep.add(Dep.target)
}
return val
},
set(newVal){
if(newVal === val){
return
}
val = newVal
if(isObj(newVal)){
observe(newVal)
}
dep.run()
}
})
if(isObj(data[key])){
observe(data[key])
}
}
}
function compile(el,vue){
let dom = document.querySelector(el)
let fragment = document.createDocumentFragment()
while(child = dom.firstChild){
fragment.append(child)
}
let reg = /\{\{(.*)\}\}/
replace(fragment)
function replace(fragment){
Array.from(fragment.childNodes).forEach(node=>{
if(node.nodeType === 3 && reg.test(node.textContent)){
let text = node.textContent
let l = RegExp.$1.split(".")
let val = vue
l.forEach(item=>{
val = val[item]
})
node.textContent = text.replace(reg,val)
new Watch(vue,l,function(newVal){
node.textContent = text.replace(/\{\{(.*)\}\}/,newVal)
})
}
if(node.childNodes){
replace(node)
}
})
}
dom.appendChild(fragment)
}
function Dep() {
this.list = []
}
Dep.prototype.add = function(watch) {
this.list.push(watch)
}
Dep.prototype.run = function(){
this.list.forEach(item=>{
item.update()
})
}
function Watch(vue,l,fn){
this.vue = vue
this.l = l
this.fn = fn
Dep.target = this
let val = vue
l.forEach(item=>{
val = val[item]
})
//变成null是因为你执行update的时候不会把把watch再放进list
Dep.target = null
}
Watch.prototype.update = function(){
let val = this.vue
this.l.forEach(item=>{
val = val[item]
})
this.fn(val)
}
let vue = new Vue({
el:"#app",
data:{a:{b:1},c:2}
})
</script>
</body>
</html>
vue源码分析之视图连接数据(四)
最新推荐文章于 2024-10-03 16:14:13 发布