本篇绪论
- 1,Vue响应式原理
1,Vue响应式原理
在vue实例中声明的数据就是响应式的。响应式:数据发生改变,视图会重新渲染新的值。
vue是怎么知道数据改变的呢;vue在数据改变的时候,怎么知道通知哪些视图更新呢;vue数据改变的时候,视图怎么知道什么时候更新呢?
首先介绍下Object.defineProperty
Object.defineProperty可以为对象中的每一个属性,设置get、set方法,当属性被访问的时候会触发get函数,当属性被赋值/改变时,会触发set函数。
eg
var obj = {
name: 'xiaowang'
}
Object.defineProperty(obj, "name", {
get() {
console.log('get触发')
},
set(val) {
console.log('set触发')
}
})
当访问obj.name时,会打印get触发
当为obj.name赋值时,obj.name=100会打印set触发
vue是怎么知道数据改变的呢?因为vue在属性的set方法中做了手脚,因此当数据改变的时候,触发属性的set方法,vue就能知道数据有改变。
依赖收集
data中声明的每个属性,都拥有一个数组,保存着谁依赖(使用)了它。
eg:
data() {
return {
name: 'xiaowang'
}
}
页面中引用 {{name}}
此时,name把页面存在它的后宫中(这个页面依赖我),因为它知道谁依赖它之后,他就可以在发生改变的时候,通知依赖它的页面,从而让页面完成更新。
这就是依赖收集,把依赖了我(使用了我)统统保存起来。
为什么要依赖收集?
在使用vue时,我们经常会遇到在data中声明的属性,有的并没有在template里展示,但是我们即将修改这个属性的值,那么就会造成视图更新,这是没有必要的,eg:
<template>
{{msg1}}
</template>
data () {
return {
msg1: 11111,
msg2: 22222
}
},
mounted () {
this.msg2 = 33333
}
我们改变了msg2的值,但是在template里并没有使用这个值,所以并不需要通知视图,进行更新,所以这里我们就需要进行依赖收集,避免不必要的视图更新。
- data中每个声明的属性,都会有一个专属的依赖收集器subs
- 当页面使用到某个属性的时候,页面的watcher就会被放在依赖收集器subs中
数据是在什么时候进行收集依赖的呢:在Object.defineProperty的get函数时。当页面读取了name,会触发name的get函数,此时,name就会保存页面的watcher了
依赖更新
就是通知所有的依赖进行更新。
每个属性都会保存一个依赖收集器subs,它是用来在数据发生变化时,通知更新的
Object.defineProperty的set方法,当name放生改变时,name会遍历自己的依赖收集器subs,逐个通知watcher,让watcher完成更新。
数据变化会触发set函数,通知视图,视图开始更新
- Object.defineProperty的get函数,用于依赖收集
- Object.defineProperty的set函数,用于依赖更新
- 每个data声明的属性,都拥有一个专属依赖收集器subs
- 依赖收集器subs保存的依赖是watcher
- watcher可用于进行视图更新
Object.defineProperty
是在对象上定义一个新的属性,或者改变一个对象现有的属性,并且返回这个对象。
var str
var obj = {}
Object.defineProperty(obj, "b", {
get(){
console.log('get b')
return str
},
set(newVal){
console.log('set b')
str = newVal
},
enumerable : true,
configurable : true
})
obj.b = 100
console.log(obj.b)

下面例子实现一个极简单的vue双向数据绑定
<body>
<input type="text" id="txt">
<span id="content"></span>
</body>
<script>
var txt = document.querySelector('#txt'),
content = document.querySelector('#content'),
obj = {}
Object.defineProperty(obj, 'msg', {
set (val) {
txt.value = val
content.innerHTML = val
}
})
txt.addEventListener('keyup', function (e) {
obj.msg = e.target.value
})
观察者模式
它分为注册环节和发布环节
比如我们去剪头发,但是需要排队,我们不想在店内傻傻等,就会选择出去逛会街隔段时间回来看看排队的人还多吗,这样的话,我可能逛街逛累了不想剪了,这样店家就会流失像我这样的顾客。所以理发店想了个方法,会把客户的电话留下,其实这就是观察者模式中的注册环节。然后排到我的时候,会打电话通知我,这就是观察者的发布模式。

网友评论