Vue响应式原理及双向数据绑定示例分析
目录
- 前言
- 响应式原理
- 双向数据绑定
前言 之前公司招人,面试了一些的前端同学,因为公司使用的前端技术是
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
属性的赋值。上述的组件就相当于如下代码
{{localValue}}
{{localValue}}.count {color: red; }

文章图片
因此当我们修改input输入框中的值时,我们通过v-model绑定的值也会同步修改,基于上述原理,我们可以很容易的实现一个数据双向绑定的组件。
v-model实践 【Vue响应式原理及双向数据绑定示例分析】首先我们定义一个
Vue
组件,相信大家已经很熟悉了。click me {{value}}
上面的组件定了我们通过在
props
中添加value
属性,并且在值更新时触发input
事件。created
钩子和watch
中为localvalue
赋值是为了同步父组件状态到子组件中。通过上面的组件定义,我们就可以在组件上使用
v-model
指令做双向数据绑定了。父组件{{count}}
下面是实际效果

文章图片
import Vue from 'https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.esm.browser.js'Vue.directive('mymodel', {bind(el, binding, vnode, oldVnode) {//组件和原生input标签需要分别处理,el.value = https://www.it610.com/article/binding.value; if (vnode.tag =='input') {//监听绑定的变量vnode.context.$watch(binding.expression, (v) => {el.value = https://www.it610.com/article/v; })//添加inout事件监听el.addEventListener('input', (e) => {//context是input所在的父组件,这一步是同步数据vnode.context[binding.expression] = e.target.value; })} else { //组件//vnode的结构可以参见文档。不过我觉得最直观的方法就是直接在控制台打印处理let {componentInstance,componentOptions,context} = vnode; const {_props} = componentInstance; //处理model选项if (!componentOptions.Ctor.extendOptions.model) {componentOptions.Ctor.extendOptions.model = {value: 'value',event: 'input'}}let modelValue = https://www.it610.com/article/componentOptions.Ctor.extendOptions.model.value; let modelEvent = componentOptions.Ctor.extendOptions.model.event; //属性绑定,这里直接修改了属性,没有想到更好的办法,友好的意见希望可以提出console.log(binding)_props[modelValue] = binding.value; context.$watch(binding.expression, (v) => {_props[modelValue] = v; })//添加事件处理函数,做数据同步componentInstance.$on(modelEvent, (v) => {context[binding.expression] = v; })}},inserted() {},update() {},componentUpdated() {},unbind() {},})Vue.component('add-one', {template: 'click me {{localvalue}}',props: {value: {type: Number | String,default: -1}},//自定义value和事件// model: {//value: 'count',//event: 'change'// },watch: {//监听value变化,更新组件localvalue状态value(v) {this.localvalue = https://www.it610.com/article/v; }},methods: {//事件触发localvalue变更,通过事件同步父组件状态变更addCount() {this.localvalue++; this.$emit('input', this.localvalue); }},data() {return {localvalue: 0}},created() {//初始化获取value值console.log(this.value)this.localvalue = https://www.it610.com/article/this.value; }})new Vue({el:'#app',data() {return {count: 0,}; },methods: {},created() {}})
当然我们也可以不使用
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); }},}
通过上面的组件定义
就相当于
{{count}}
只不过
v-model
指令帮我们做上面的事件添加,属性绑定和状态同步操作罢了。以上就是Vue响应式原理及双向数据绑定示例分析的详细内容,更多关于Vue响应式双向数据绑定的资料请关注脚本之家其它相关文章!
推荐阅读
- VueJS设计与实现之浅响应与深响应详解
- vue在同一个页面重复引用相同组件如何区分二者
- Vue中实现过渡动画效果示例代码
- Apache|Apache DolphinScheduler 3.0.0 正式版发布!
- Springboot打印接口的三种方式分享
- VUE使用localstorage和sessionstorage实现登录示例详解
- 分布式系统与计算|BigData NoSQL —— ApsaraDB HBase数据存储与分析平台概览
- 科股早知道|钛媒体科股早知道:光伏需求最短板,四季度缺口或更大,行业未来2-3年处于高景气周期;美国芯片法案正式落地,海外各国豪掷重金加码芯片
- 一室一厅美式装修,羡煞旁人
- 如何仿建网站(附带个人博客样式搭建实例)