react & vue & angular

Vue v-model 的原理

2022-12-08  本文已影响0人  Cherry丶小丸子

你可以用 v-model 指令在表单 <input>、<textarea> 及 <select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理

v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:

  • text 和 textarea 使用 value 作为 prop 和 使用 input 作为事件;
  • checkbox 和 radio 使用 checked 作为 prop 和 使用 change 作为事件;
  • select 使用 value 作为 prop 和 使用 change 作为事件;
v-model 的原理

v-model 的原理其实是背后有两个操作
1、v-bind 绑定 value 属性的值;
2、v-on 绑定 input 事件监听到函数中,函数会获取最新的值赋值到绑定的属性中;

// 在原生元素上使用 v-model 时

<input v-model="inputValue">

等价于:

<input :value="inputValue" @input="inputValue = $event.target.value">
那 v-model 是单向数据流吗?

是的,虽然官方没有明确表示这点,但我们可以捋一捋两者的关系。

什么是单项数据流?

父组件可以向子组件传递数据,并且改变子组件的值,而子组件不能改变父组件传递给它的 prop 属性,官方推荐的做法是子组件抛出事件,通知父组件自行改变绑定的值。

v-model 做法完全符合单项数据流。甚至于,它给出了一种在命名和事件定义上的规范。
众所周知 .sync 修饰符是单向数据流的另一个典型范式。


image.png

单向数据流:总结起来其实也就 8 个字:数据向下,事件向上

v-model 的特殊用法

一般情况,咱们使用 v-model 主要是用于数据的双向绑定,可以十分方便的获取到用户的输入值。
但在某些特殊情况下,我们也可以将 v-model 用于父子组件之间数据的双向绑定(在组件上使用 v-model)

// 当在组件上使用 v-model 时
<custom-input v-model="inputValue"></custom-input>

等价于:

<custom-input :value="inputValue" @input="inputValue = $event"></custom-input>

例如:

// 父组件
<template>
    <div id="app">
        <custom-input v-model="userName"></custom-input>
    </div>
</template>

<script>
    import CustomInput from './components/custom-input'
    export default {
        name: 'App',
        components: { CustomInput },
        data(){
            return {
                userName: ''
            }
        }
    }
</script>
// 子组件
<template>
    <div class="custom-input">
        <input type="text" :value="value" @input="handleInput"/>
    </div>
</template>

<script>
    export default {
        name: "custom-input",
        props: {
            value:{ // 获取父组件的数据 value
                type: String,
                default: ''
            }
        },
        methods: {
            handleInput(e){
                this.$emit('input', e.target.value) // 触发父组件的 input 事件
            }
        }
    }
</script>
自定义组件的 v-model

默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,
但是一些输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突

// 子组件
<template>
    <div class="custom-checkbox">
        <input type="checkbox" :checked="checked" @change="handleChange" />
    </div>
</template>

<script>
    export default {
        name: "custom-checkbox",
        // 允许一个自定义组件在使用 v-model 时定制 prop 和 event
        model: {
            prop: 'checked',
            event: 'change'
        },
        props: {
            checked:{ // 获取父组件的数据 checked
                type: Boolean,
                default: false
            },
            value: String,
        },
        methods: {
            handleChange(e){
                this.$emit('change', e.target.checked) // 触发父组件的 change 事件
            }
        }
    }
</script>

现在 在这个组件上使用 v-model 的时候
<custom-checkbox v-model="isUserName" value="some value"></custom-checkbox>

等价于:

<custom-checkbox :checked="isUserName" @change="isUserName = $event" value="some value"></custom-checkbox>
上一篇 下一篇

猜你喜欢

热点阅读