不要再搞混Vue的响应式原理和双向数据绑定了

更新日期: 2022-09-02阅读: 1.2k标签: 数据绑定

前言

之前公司招人,面试了一些的前端同学,因为公司使用的前端技术是 vue ,所以免不了问到其响应式原理和 Vue 的双向数据绑定。但是这边面试到的80%的同学会把两者搞混,通常我要是先问响应式原理再问双向数据绑定原理,来面试的同学大都会认为是一回事,那么这里我们就说一下二者的区别。


响应式原理

是Vue的核心特性之一,数据驱动视图,我们修改数据视图随之响应更新,就很优雅~

Vue2.x 是借助 Object.defineProperty() 实现的,而 Vue3.x 是借助 Proxy 实现的,下面我们先来看一下2.x的实现。

Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
//拦截get,当我们访问data.key时会被这个方法拦截到
get: function getter () {
//我们在这里收集依赖
return obj[key];
},
//拦截set,当我们为data.key赋值时会被这个方法拦截到
set: function setter (newVal) {
//当数据变更时,通知依赖项变更UI
}
})

我们通过 Object.defineProperty 为对象 obj 添加属性,可以设置对象属性的 getter 和 setter 函数。之后我们每次通过点语法获取属性都会执行这里的 getter 函数,在这个函数中我们会把调用此属性的依赖收集到一个集合中 ;而在我们给属性赋值(修改属性)时,会触发这里定义的 setter 函数,在次函数中会去通知集合中的依赖更新,做到数据变更驱动视图变更。

3.x的与2.x的核心思想一致,只不过数据的劫持使用 Proxy 而不是 Object.defineProperty ,只不过Proxy相比Object.defineProperty在处理数组和新增属性的响应式处理上更加方便。

let nObj=new Proxy(obj,{
//拦截get,当我们访问nObj.key时会被这个方法拦截到
get: function (target, propKey, receiver) {
console.log(`getting ${propKey}!`);
return Reflect.get(target, propKey, receiver);
},
//拦截set,当我们为nObj.key赋值时会被这个方法拦截到
set: function (target, propKey, value, receiver) {
console.log(`setting ${propKey}!`);
return Reflect.set(target, propKey, value, receiver);
}
})

Proxy 的详细使用方法参考ES6教程

Vue 的响应式原理的实现细节相信大多数同学已经很熟悉了,这里就不在展开细谈了,如果还想更详细的了解,或者想要做一个简易的 Vue 实现,可以参考这篇Vue原理,相信你会有不小收获。


双向数据绑定

双向数据绑定通常是指我们使用的 v-model 指令的实现,是 Vue 的一个特性,也可以说是一个 input 事件和 value 的语法糖。 Vue 通过 v-model 指令为组件添加上 input 事件处理和 value 属性的赋值。

<template>
<input v-model='localValue'/>
</template>

上述的组件就相当于如下代码

<template>
<!-- 这里添加了input时间的监听和value的属性绑定 -->
<input @input='onInput' :value='localValue' />
<span>{{localValue}}</span>
</template>
<script>
export default{
data(){
return {
localValue:'',
}
},
methods:{
onInput(v){
//在input事件的处理函数中更新value的绑定值
this.localValue=v.target.value;
console.log(this.localValue)
}
}
}
</script>

因此当我们修改input输入框中的值时,我们通过v-model绑定的值也会同步修改,基于上述原理,我们可以很容易的实现一个数据双向绑定的组件。


v-model实践

首先我们定义一个 Vue 组件,相信大家已经很熟悉了。

<tempalte>
<div class="count" @click="addCount">click me {{value}}</div>
</template>
<script>
export default{
props:{
//关键的第一步:设置一个value属性
value:{
type:Number,
default:0
}
},
watch:{
//监听value变化,更新组件localvalue状态
value(v){
this.localvalue=v;
}
},
methods:{
//关键的第二步:事件触发localvalue变更,通过事件同步父组件状态变更
addCount(){
this.localvalue++;
this.$emit('input',this.localvalue);
}
},
data(){
return{
//组件状态,遵守单项数据流原则,不直接修改props中的属性
localvalue:0
}
},
created(){
//初始化获取value值
this.localvalue=this.value;
}
}
</script>

上面的组件定了我们通过在 props 中添加 value 属性,并且在值更新时触发 input 事件。 created 钩子和 watch 中为 localvalue 赋值是为了同步父组件状态到子组件中。通过上面:point_up_2:的组件定义,我们就可以在组件上使用 v-model 指令做双向数据绑定了。

<template>
<add-one v-model="count"></add-one>
<span>父组件{{count}}</span>
</tempalte>
<script>
export default{
data() {
return {
count: 0,
};
},
methods: {
},
created(){
}
}
</script>

下面是实际效果 当然我们也可以不使用 value 和 input 事件这样的组合,为了更使得组件的定义更加符合语义,我们也可以自定义要实现双向绑定的属性和事件。我们在组件的 model 选项中设置 value 和 event 即可。如下:

export default{
//这里做了一个value和event的映射
model:{
value:'count',
event:'change'
},
props:{
//关键的第一步:设置一个value属性
count:{
type:Number,
default:0
}
},
methods:{
//关键的第二步:事件触发localvalue变更,通过事件同步父组件状态变更
addCount(){
this.localvalue++;
this.$emit('change',this.localvalue);
}
},
}

通过上面的组件定义

<add-one v-model="count"></add-one>

就相当于

<template>
<add-one @change='onChange' :count='count'></add-one>
<span>{{count}}</span>
</template>
<script>
export default{
data(){
return {
count:0,
}
},
methods:{
onChange(v){
this.count=v;
console.log(this.count)
}
}
}
</script>

只不过 v-model 指令帮我们做上面的事件添加,属性绑定和状态同步操作罢了。 这里埋下一个小伏笔,不知道同学们熟不熟悉*Vue的自定义指令*,不熟悉的同学可以在评论区留言,下篇提前把使用自定义指令的各种技巧为各位同学奉上,附带v-model的具体实现。

加更:自定义指令的各种技巧和v-model的实现已完成,感兴趣的同学可以看一下理论+实践,彻底掌握Vue自定义指令。


结语

以上就是本人关于 Vue 响应式原理和双向数据绑定原理的理解

作者:一拳不是超人
链接:https://juejin.cn/post/7117424554107994120

链接: https://fly63.com/article/detial/12079

vue在自定义组件中使用v-model进行数据绑定

有这么一句话: 默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event。先来一个组件,不用vue-model,正常父子通信;点击回应后,父亲对儿子说的话变成了儿子的回应。儿子收到的信息也变了,实现通信。

Angular双向数据绑定

双向数据绑定: 所谓双向数据绑定是指View(视图)与Model(模型)之间的绑定:View<=>Model。View的改变: 通过界面交互使视图发生改变,如Input框的输入,Select元素的选择,scrollBar滚动,浏览器窗口大小改变等等。

Nautil 中使用双向数据绑定

虽然是基于 react 的框架,但是在 nautil 中可以使用双向数据绑定,这得益于基于观察者模式的开发思路。在 react 中使用双向绑定并非没有需求,react 严格的单向数据流,严重影响了开发者的发挥空间,特别是在表单组件的使用中

组件使用v-model、$listeners、.sync(区别于v-model的双向数据绑定)

首先我们先说一下在自定义组件中使用v-model的必要条件,在自定义的组件中要有input(这里我们先不讨论单选复选框),在自定义组件的模板对象中要有props属性,且里面要含有一个value

Vue的双向数据绑定原理

Object属性分为两个类型:数据属性、访问器属性,每类属性又有其不同的特显,双向绑定的原理是根据其访问器属性的特性来实现的。Configurable:是否可以通过delete删除,能否修改他的属性特性,能否修改为访问器属性。默认值true

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!