vue 双向数据绑定

145 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情

vue 中有两个“特别的”概念:响应式双向数据绑定

其实响应式原理是一种单向行为:它是数据到 DOM (也就是view视图)的映射;而真正的双向绑定,除了数据变化会引起 DOM 的变化之外,还应该在操作 DOM 改变后反过来影响数据的变化!

vue 中提供了(内置的) v-model指令实现双向绑定。

v-model和双向绑定的简单实现

首先,v-model并不是可作用到任意标签,它只能在一些特定的表单标签如 inputselecttextarea以及自定义组件中使用。

通常你会了解到 v-model其实只是一个语法糖,它实际是依靠v-bind:绑定响应式数据 & 触发 input 绑定事件并传递数据。

这么说也可以:

<input v-model="value">

<!--可以认为等价于-->
<input
    v-bind:value="value"
    v-on:input="value= $event.target.value"
>

我们用自定义组件和上面代码来实现一个类似v-model的数据绑定:

<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="root"></div>
<script type="text/javascript">
    const component = {
        template: `
            <div>
                <input type="text" @input="handleInput">
            </div>
        `,
        methods: {
            handleInput (e) {
                this.$emit('input', e.target.value)
            }
        }
    }
    let vm = new Vue({
        conponents: {
            CompA: component
        },
        el: '#root',
        template: `
            <div>
                <comp-a></comp-a>
            </div>
        `
    })
</script>

这样一个初始化的 demo 就搭建好了:

  • 我们定义了一个组件component,实例化了一个 Vue 对象。v-model绑定的值,是从外层的 Vue 实例中传进去的。
  • 首先我们要在组件 component 里面定义一个 props
  • 然后就可以在 Vue 实例的 template 模板里面去加上这个 value ,同时绑定input事件;
  • 同样,组件component里面的 input 也得绑定 value :

我们将上面代码中script部分完善一下:

const component = {
    props: ['value'],
    template: `
        <div>
            <input type="text" @input="handleInput" :value="value">
        </div>
    `,
    methods: {
        handleInput (e) {
            this.$emit('input', e.target.value)
        }
    }
}

let vm = new Vue({
    components: {
        CompA: component
    },
    el: '#root',
    template: `
        <div>
            <div>{{value}}</div>
            <comp-a :value="value" @input="_handleInput"></comp-a>
        </div>
    `,
    data () {
        return {
            value: 'mxcnb'
        }
    },
    methods:{
        _handleInput(e){
            this.value=e
        }
    }
})

既然是双向绑定,我们不妨试着改变一下 value 的值:

<button @click="handleInput">改变</button>
handleInput(){
    this.value='1231'
},

嗯,确实改变了。

我们大概了解了:vue双向数据绑定的原理是通过 prop 向组件传递数据(对自定义组件来说就是:在数据渲染时使用 prop 渲染数据,将 prop 绑定到子组件自身的数据上);并监听自定义事件接受组件反传的数据并更新(对自定义组件来说就是:修改数据时更新自身数据来替代 prop ,监听子组件自身数据的改变,触发事件通知父组件更改绑定到prop的数据)。

这里监听的事件对原生input组件来说就是内置的onUpdate:modelValue函数;对自定义组件来说就是自定义事件;

通过 prop 传递的数据就是v-bind绑定的data;

反传的数据就是用户输入后改变了的value;

为了进一步体验“监听子组件数据”的过程,我们完全可以将上面 components 部分修改如下:

const component = {
    props: ['value'],
    template: `
        <div>
            <input type="text" v-model="_value">
        </div>
    `,
    computed:{
        _value:{
            get(){
                return this.value
            },
            set(value){
                this.$emit('input', value)
            }
        }
    },
}

翻译自:fadamakis.medium.com/