<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
</style>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<h1 id="name"></h1>
<input type="text">
<input type="button" value="改变data内容" onclick="changeInput()">
<script type="text/javascript">
let log = console.log.bind(console)
// 数据观测
function observe(obj){
if( !obj || typeof obj !== 'object'){
return
}
let keys = Object.keys(obj)
keys.forEach( key =>{
observeable(obj, key, obj[key])
})
return obj
}
function observeable(obj, key, value){
let dep = new Dep()
Object.defineProperty(obj, key, {
get(){
dep.depend()
console.log(`${key}属性被读取了`);
return value
},
set(newVal){
value = newVal
console.log(`${key}属性被修改了`);
dep.notify()
}
})
}
// 订阅收集器
class Dep{
constructor(){
this.subs = []
}
depend(){
if( Dep.target ){
this.addSub(Dep.target)
}
}
addSub(target){
this.subs.push(target)
}
notify(){
this.subs.forEach(sub =>{
sub.update()
})
}
}
Dep.target = null
// 订阅者
class Watcher{
constructor(vm, exp, cb){
this.vm = vm // vm实例对象
this.exp = exp // 绑定的属性
this.cb = cb // 数据变化的回调函数
this.value = this.get()
}
update(){
let newVal = this.vm.date[this.exp]
let oldVal = this.value
if( newVal !== oldVal){
this.value = newVal
this.cb.call(this.vm, newVal, oldVal)
}
}
get(){
Dep.target = this
let value = this.vm.date[this.exp]
Dep.target = null
return value
}
}
function MyVue(date, ele, exp){
this.date = date
// 数据可观测性
observe(this.date)
log(this.date)
// 初始化数据
ele.innerHTML = this.date[exp]
// 订阅者绑定
new Watcher(this, exp, function(val){
ele.innerHTML = val
})
return this
}
let ele = document.querySelector('#name');
let input = document.querySelector('input');
let myVue = new MyVue({
name: '初始化数据'
}, ele, 'name')
// 改变输入框
input.oninput = function(e){
log(myVue)
myVue.date.name = e.target.value
}
// 修改date内容
function changeInput(){
log(myVue)
myVue.date.name = '修改date内容'
}
</script>
</body>
</html>
参考地址:
https://www.jianshu.com/p/5990a386132a