一文详解Vue的响应式原则与双向数据绑定
作者:web前端开发
反应性原则
它是 Vue.js 的核心特性之一,一个数据驱动的视图,我们修改数据视图来响应更新,非常优雅。
Vue2.x 使用 Object.defineProperty() 实现,而 Vue3.x 使用 Proxy 实现。 我们先来看看2.x的实现。
Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function getter () { return obj[key]; }, set: function setter (newVal) { ... } })
我们通过Object.defineProperty给对象obj添加属性,可以设置对象属性的getter和setter函数。
之后,我们每通过点语法获取一个属性,就会执行这里的getter函数。 在这个函数中,我们会将调用这个属性的依赖收集到一个集合中; 当我们给属性赋值时,这个定义就会被触发。 setter函数,在辅助函数中,会通知集合中的依赖更新,让数据变化驱动视图变化。
3.x的核心思想和2.x一样,只是在数据劫持上使用了Proxy而不是Object.defineProperty,但是在处理数组和响应式处理新属性时Proxy比Object.defineProperty更方便 .
let nObj=new Proxy(obj,{ get: function (target, propKey, receiver) { console.log(`getting ${propKey}!`); return Reflect.get(target, propKey, receiver); }, set: function (target, propKey, value, receiver) { console.log(`setting ${propKey}!`); return Reflect.set(target, propKey, value, receiver); } })
Vue响应式原理的实现细节相信大部分人已经很熟悉了,这里不再赘述。
双向数据绑定
双向数据绑定通常是指我们使用的 v-model 指令的实现。 它是 Vue 的一个特性,也可以说是输入事件和值的语法糖。 Vue 通过 v-model 指令为组件添加输入事件处理和值属性赋值。
<template> <input v-model='localValue'/> </template>
上面的组件等价于下面的代码。
<template> <input @input='onInput' :value='localValue' /> <span>{{localValue}}</span> </template> <script> export default{ data(){ return { localValue:'', } }, methods:{ onInput(v){ this.localValue=v.target.value; console.log(this.localValue) } } } </script>
因此,当我们修改输入框的值时,我们通过v-model绑定的值也会同步修改。 基于以上原理,我们可以轻松实现一个双向数据绑定组件。
v-model实践
首先,我们定义一个Vue组件:
<tempalte> <div class="count" @click="addCount">click me {{value}}</div> </template> <script> export default{ props:{ value:{ type:Number, default:0 } }, watch:{ value(v){ this.localvalue=v; } }, methods:{ addCount(){ this.localvalue++; this.$emit('input',this.localvalue); } }, data(){ return{ localvalue:0 } }, created(){ this.localvalue=this.value; } } </script>
上面的组件指定我们在 props 中添加 value 属性,并在 value 更新时触发 input 事件。 在创建的 hook 和 watch 中对 localvalue 的赋值是将父组件的状态同步到子组件。
通过上面的组件定义,我们可以使用 v-model 指令对组件进行双向数据绑定。
<template> <add-one v-model="count"></add-one> <span>The parent component{{count}}</span> </tempalte> <script> export default{ data() { return { count: 0, }; }, methods: { }, created(){ } } </script>
以下是实际效果。
当然,我们也可以不使用 value 和 input 事件的组合。 为了让组件的定义更加语义化,我们还可以自定义属性和事件,实现双向绑定。 我们可以在组件的模型选项中设置值和事件。 如下:
export default{ model:{ value:'count', event:'change' }, props:{ count:{ type:Number, default:0 } }, methods:{ 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的响应式原则与双向数据绑定的文章就介绍到这了,更多相关Vue双向数据绑定内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!