数据发生改变,界面跟着更新,如图所示:
<!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>Document</title>
</head>
<body>
<div id="app">
{{message}}
{{message}}
{{message}}
</div>
<script src="../Vue源码/vue-2.6.14/dist/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data(){
return{
message:'哈哈哈'
}
}
})
</script>
</body>
</html>
这就是 vue 的响应式,那么 vue 内部是如何实现的呢?
1.app.message 修改数据,Vue 内部是如何监听 message 数据发生改变的 ?
vue 内部是通过 Object.defineProperty 监听对象属性的改变
2.当数据发生改变时,Vue 是如何通知哪些地方刷新界面的 ?
通过发布订阅者模式来通知哪些页面需要进行刷新
<script>
const obj = {// 首先拿到数据对象
message:'哈哈哈',
name:'why'
}
Object.keys(obj).forEach(key => {// 然后遍历对象,拿到里面的每一个 key 和 值
let value = obj[key]
//重新定义 obj,增加了两个方法 set 和 get
Object.defineProperty(obj, key, {
set(newValue){//值发生改变时执行该函数,获取新值
console.log('监听' + key +'改变')
//哪里使用就通知哪里,如何确定哪里进行了使用呢?-----解析html获取哪里进行了使用(发布订阅者模式)
value = newValue
dep.notify()// 订阅者发生改变
},
get(){//监听对应的值
console.log('获取'+ key + '对应的值')
return value
}
})
})
//发布者订阅者模式
//1.发布者
class Dep {
constructor(){// new Dep() 的时候调用 constructor
this.subs = []
}
addSub(watcher){//把订阅者添加进来
this.subs.push(watcher)
}
notify(){//用来通知订阅者发生改变
this.subs.forEach(item =>{
item.update()
})
}
}
//2.订阅者
class Watcher{
constructor(name){
this.name = name
}
update(){//在这里更新界面
console.log(this.name + '发生update')
}
}
const dep = new Dep()
const w1 = new Watcher('item1')
dep.addSub(w1)
const w2 = new Watcher('item2')
dep.addSub(w2)
const w3 = new Watcher('item3')
dep.addSub(w3)
</script>
vue 的响应式原理如图: