Object.defineProperty
数据响应式使用的底层API是Object.definePorperty
Object.definePorperty中可以定义set和get方法,对对象属性进行拦截。设置对象属性的值时,会自动触发set方法;获取对象属性的值时,会自动触发get方法。
核心思想是:set方法中实现dom更新的逻辑,从而实现数据值一旦变化就能更新dom的目的,也就是从model到view的更新。
以data对象为例:
let data = {
name: "柴柴老师",
age: 29
}
第一步,通过Object.defineProperty逐个定义data中所有的key,完成所有属性值变化时的拦截功能
第二步,为了更精准的实现某一个属性值变化时只更新绑定了该属性名称的dom元素值,则需要使用发布订阅功能。
发布订阅的实现:页面渲染完成后,先遍历所有dom对象,找到有v-text或v-model属性的dom节点上,并且将v-tex或v-model属性值作为key,将该dom节点的赋值函数作为数组的元素,存储成一个map。
第三步,在set方法中,调用该key值对应的dom更新函数集。当data某个属性name变化时,则直接执行对应key值name的函数集,实现精准更新需要更新的dom。
第四步,v-text是单向绑定,v-model是input组件的双向绑定。从视图view到model的绑定,则要在第二步中找到有v-model属性的dom节点时,给该节点上增加监听值变化的事件,将新值赋值给data对应的属性
代码截图为bilibili上柴柴老师的视频:
v-model
组件身上添加v-model ,一般用于组件内部有可输入的控件,比如说input textarea内容编辑,目的是为了实现双向绑定
一旦组件身上写了v-model之后相当于:1.名称为value的自定义属性的绑定2.名称为input自定义事件的绑定 ,如editor组件写了v-model:
<Editor v-model="content"/>
等价于
<Editor :value="content" @input=""/>
以上可以总结为2点:
1、子组件Editor可以通过定义名为value的props来接收参数
2、子组件通过触发$emit('input',‘子组件数据')实现将子组件的数据传到父组件中
特别注意:V-model语法糖下 我们并不需要父组件中定义接受传入实参的方法