1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<script>
function Vue(options){
// 1、响应式处理
this.$options = options;
this.$data = options.data()
observer(this.$data)
}
Vue.prototype.$mount = function(sel){
//获得渲染之后的dom结构,追加到宿主元素
//创建更新函数,$mount就是初始化
this.updata = function(){
console.log('undata')
//首次执行,执行挂载
const vnode = this.$options.render.call(this)

if(!this.isMounted){
const parent = document.querySelector(sel)
this.patch(parent,vnode)
this.isMounted = true
// 如果有生命周期函数
parent.appendChild(child)
if(this.$options.mounted){
//指定下上下文
this.$options.mounted.call(this)
}
}else{
// 以后执行更新
//_vnode就是上一次虚拟dom
this.patch(this._vnode,vnode)
}
this._vnode = vnode

}
this.updata()
}
Vue.prototype.createElement = function(tag,props,children){
return {tag,props,children}
}
//n1是宿主元素或旧的vnode,n2是新vnode
Vue.prototype.patch= function(n1,n2){

}
//拦截对象属性方法
function observer(obj){
Object.keys(obj).forEach(key=>{defineReactive(obj,key,obj[key])})
//遍历obj每一个key,
}

//定义一个响应式
function defineReactive(obj,key,val){
Object.defineProperty(obj,key,{
get(){
console.log('get',key)
//典型的闭包应用,每执行一次defineReactive,就保存一次变量
return val
},
set(newVal){
if(newVal !== val){
val = newVal
kvue.updata()
}
}
})
}
</script>
<script>
const kvue = new Vue({
data(){
return {
title:'标题'
}
},
mounted(){
setTimeout(()=>{
this.$data.title = '标题变了'
},1000)
},
render(){
return h('h3',null,this.$data.title)
}
})
kvue.$mount('#app')

</script>