双向数据绑定的原理
采用数据劫持结合发布者-订阅者模式的方式
data
数据在初始化时,会实例化一个Observe
类,它对data
数据进行递归遍历,并通过Object.defineProperty
方法,给每个值添加上一个getter
和setter
。在数据读取时,会触发getter
进行依赖收集;在数据改变时,会触发setter
,对刚收集的依赖进行触发,并且更新watcher,
通知视图进行渲染。
使用 Object.defineProperty() 来进行数据劫持有什么缺点?
只能监听到数据的修改,监听不到数据的新增和删除,从而不能触发组件更新渲染。vue2中会对数组的新增删除方法push、pop、shift、unshift、splice、sort、reserve
通过重写的形式,在拦截里面进行手动收集触发依赖更新。
和Vue3相比有什么区别?
Vue3
采用了Proxy
代理的方式,它提供了一个用于创建代理对象的构造函数。它对整个对象监听和拦截,可对对象所有操作进行处理。
而Object.defineProperty
只能监听单个属性的读写,无法监听新增、删除等操作。
Vue是如何收集依赖的?
依赖收集发生在defineReactive()
方法中,在方法内new Dep()
实例化一个Dep()
实例,然后在getter
中通过dep.depend()
方法对数据依赖进行收集,然后在settter
中通过dep.notify()
通知更新。整个Dep
是一个观察者,把收集的依赖存储起来,在需要的时候进行调用。在收集数据依赖的时候,会为数据创建一个Watcher
,当数据发生改变通知每个Watcher
,由Wathcer
进行更新渲染。
data为什么是函数而不是对象?
data() { return {} }
- 对象是引用类型的数据,当多个实例引用同一个对象时,只要一个实例对这个对象进行操作,其他实例中的数据也会发生变化。
- 在 Vue 中大多为了复用组件,当每次复用组件的时候,就会返回一个新的 data,那就需要每个组件都是私有数据空间,这样组件之间才不会相互干扰。它们各自维护自己的数据,不会干扰其他组件的正常运行。
- 利用函数的格式,数据会以函数返回值的形式定义。
v-model 是如何实现的,语法糖是什么?
Vue 中数据双向绑定是一个指令v-model
,可以绑定一个响应式数据到视图,同时视图的变化能改变该值。
- 当作用在表单上:通过
v-bind:value
绑定数据,v-on:input
来监听数据变化并修改value
- 当作用在组件上:本质上是一个父子通信语法糖,通过
props
和$emit
实现。
语法糖写法:
<input type="text" v-model="name" >
完整写法:
<input type="text"
v-bind:value="name"
v-on:input="name=$event.target.value">