// 如何实现简单版本的vue响应式原理
/*
响应式原理:从改变一个数据到发生改变的过程
get部分收集依赖
↓
数据改变触发set → set部分触发notify → 更改对应的虚拟dom → 更新render
*/
/*
1.构造函数(实现数据的双向绑定)
*/
/*
vue函数
vue是function,function的原型prototype是Function,
Function的原型prototype是Object
这里的Vue是构造函数
要点:实现上面的4个步骤
*/
function Vue() {
// 定义数据
this.$data = { a : 1 }
// 获取id="app"的dom元素(真实dom)
this.el = document.getElementById("app")
// 定义虚拟dom
this.virtualDom = ""
// 监听数据变化
this.observer(this.$data);
// 重新渲染
this.render()
// 构造函数,隐式创建,隐式子返回
// var this = {}
// return this
console.log(this)
}
/*
要点:vue原型prototype设置observer函数,监听数据变化(连接virtualDom,render,el,$data)
+注册getter,setter
实现12步骤,数据改变触发set+set部分触发notify(get部分收集依赖)
*/
Vue.prototype.observer = function (obj) {
var self = this;
// 都是更改this.$data,所以代理后的数据改变后也是复制给this.$data,实现响应式更新
this.$data = new Proxy(this.$data, {
// 参数这里看现代js教程的proxy and reflect
get: function (target,key) {
return target[key]
},
// 第三个参数是新值newValue
set:function (target,key,newValue) {
target[key] = newValue
self.render()
}
})
console.log(this)
}
/*
要点:实现34步骤,更改对应的虚拟dom+重新render
*/
Vue.prototype.render = function () {
// 3.更改对应的虚拟dom
this.virtualDom = 'i am ' + this.$data.a
// 4.重新render (把新的虚拟dom赋值到真实dom)
this.el.innerHTML = this.virtualDom
console.log(this) //
}
/*
2.创建实例,使用变时器setTImeout呈现效果(数据2秒后自动改变)
*/
var vm = new Vue()
setTimeout(function () {
console.log("changes")
console.log(vm.$data) // Object {a:1}
// 1. 数据改变触发set
vm.$data.a = 444
},2000)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="app">
<!-- 一定要改设置:no Wrap in <body> -->
</div>
</body>
</html>