Vue自定义组件实现 v-model 的几种方式

 更新时间:2024年02月19日 08:28:40   作者:anyup  
在 Vue 中,v-model 是一个常用的指令,用于实现表单元素和组件之间的双向绑定,当我们使用原生的表单元素时,直接使用 v-model 是很方便的,本文给大家介绍了Vue自定义组件实现 v-model 的几种方式,需要的朋友可以参考下

前言

在 Vue 中,v-model 是一个常用的指令,用于实现表单元素和组件之间的双向绑定。当我们使用原生的表单元素时,直接使用 v-model 是很方便的,但是对于自定义组件来说,要实现类似的双向绑定功能就需要一些额外的处理。

本篇文章将介绍几种在自定义组件中实现 v-model 的方式,主要如下:

  • 使用 v-model 属性:适用于表单元素

  • 定义 model 属性:适用于非表单元素

除了以上的两种方式外,还有我们通常使用的.sync  修饰符(2.3.0+ 新增),主要区别在于使用方式的不同,前者直接使用 v-model,后者使用 .sync 修饰符进行绑定

一. 单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。

注意:每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。虽然可以,但是如果你这样做了,Vue 会在浏览器的控制台中发出警告。

二. 基础原理浅析

v-model 实际上就是 props:value$emit('input') 的组合语法糖,简单来说,v-model 的使用其实做了两个比较重要的操作,理解这两个操作,我们就可以轻松实现组件的自定义 v-model

  • v-bind 绑定 value 属性的值 - props:value;

  • v-on 绑定 input 事件监听到函数中,函数会获取最新的值赋值到绑定的属性中 - $emit('input');

三. 实现 v-model 的两种方式

1. 直接使用 v-model 属性

以 input 表单元素为例,在 vue 中,我们可以直接使用 v-model 进行绑定数据,当我们在实现自定义组件custom-component进行封装 input 时,我们的组件对外暴露时也需要使用 v-model,看下面我们应该如何实现:

在自定义组件中,我们可以通过在组件内部使用 value 属性和手动触发 input 事件来实现 v-model 的双向绑定效果。具体实现如下:

<template>
  <input v-model="newValue" />
</template>

<script>
  export default {
    props: {
      value: {
        type: Boolean,
        default: false,
      },
    },
    computed: {
      newValue: {
        get() {
          return this.value;
        },
        set(val) {
          this.$emit("input", val);
        },
      },
    },
  };
</script>

使用custom-component

<custom-component v-model="newValue" />

在上述代码中,我们通过 value 属性接收父组件传入的值,并且使用 computed 的 set 属性用来监听值的更新,手动触发 $emit('input', value) 来将新值传递给父组件,从而实现双向绑定的效果。

2. 定义 model 属性

Vue 允许我们在定义组件中通过定义 model 属性来简化 v-model 的使用。通过定义 model 属性,我们可以指定组件中哪个属性的值应该作 v-model 的值。

假如我们实现一个计数器的组件custom-counter,在页面中显示两个按钮,点击按钮可以进行数值的加减操作,具体示例如下:

<template>
  <div>
    <button @click="increment">+</button>
    <span>{{ value }}</span>
    <button @click="decrement">-</button>
  </div>
</template>

<script>
  export default {
    // 当 model 为默认值时,可以将其省略
    model: {
      prop: "value", // 默认是 value
      event: "input", // 默认是 input
    },
    props: {
      value: {
        type: Number,
        default: 0,
      },
    },
    methods: {
      increment() {
        this.$emit("input", this.value + 1);
      },
      decrement() {
        this.$emit("input", this.value - 1);
      },
    },
  };
</script>

提示:当 model 为默认值时,可以将其省略

父组件中使用custom-counter

<template>
  <div>
    <custom-counter v-model="count"></custom-counter>
    <p>计数器的值为:{{ count }}</p>
  </div>
</template>

<script>
  import CustomCounter from "./CustomCounter.vue";

  export default {
    components: {
      CustomCounter,
    },
    data() {
      return {
        count: 0,
      };
    },
  };
</script>

演示效果如下图所示:

在上面的示例中,CustomCounter组件接收一个value属性来接收父组件传递的值,并在点击按钮时修改value属性的值。通过调用this.$emit('input', newValue)触发input事件,将新的value值传递给父组件进行更新。

在父组件中,使用v-model将父组件中的count属性绑定到CustomCounter组件的value属性上,绑定 input 事件监听到函数中,从而实现了数据的双向绑定。

model 是允许 vue 自定义组件使用 v-model 的关键,虽然有时我们不显性的使用它,也不影响我们在自定义组件中使用 v-model 指令,这只是因为被设置默认值。而有的时候,显示的使用,并自定义 model 的 prop 和 event 会有益。

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

四. .sync 修饰符

在有些情况下,我们可能需要对一个 prop 进行 “双向绑定”。但是,真正的双向绑定会带来维护上的问题,因为子组件可以变更父组件,且在父组件和子组件两侧都没有明显的变更来源。

这也是为什么我们推荐以 update:myPropName 的模式触发事件取而代之。

举个例子,还是上面的计数器的例子,在一个包含 count prop 的计数组件中,我们可以用以下方法表达对其赋新值的意图:

this.$emit("update:count", newCount);

然后父组件可以监听那个事件并根据需要更新一个本地的数据 property。例如:

<custom-counter v-bind:count="count" v-on:update:count="count = $event" />

我们为这种模式提供一个缩写,即 .sync 修饰符,如下:

<custom-counter :count.sync="count"></custom-counter>

以上的两种写法是等价的

注意:带有 .sync 修饰符的 v-bind 不能和表达式一起使用 (例如 v-bind:count.sync=”count + 1” 是无效的)。取而代之的是,你只能提供你想要绑定的 property 名,类似 v-model。

五. 总结

本篇文章介绍了在 Vue 自定义组中实现 v-model 的几种方式,包括定义 model 属性和使用 v-model 属性。通过以上案例实际分析,相信大家都已经了解这几种方式的创建以及应用场景,以便更加灵活地应用到实际项目中。

以上面两种方式为例,我们可以灵活地根据自己的需求选择合适的方式来实现自定义组件 v-model。如果是表单元素,可以直接使用 v-model 属性;如果是非表单元素,可以通过定义 model 属性指定组件中哪个属性的值应该作 v-model 的值。

除此之外,使用 .sync 修饰符也是进行自定义组件双向绑定的优秀选择,因此在实际开发中,选择适合自己项目需求的方式是最重要的。

以上就是Vue自定义组件实现 v-model 的几种方式的详细内容,更多关于Vue实现v-model的资料请关注脚本之家其它相关文章!

相关文章

  • 五种Vue实现加减乘除运算的方法总结

    五种Vue实现加减乘除运算的方法总结

    这篇文章主要为大家详细介绍了五种Vue实现加减乘除运算的方法,文中的示例代码简洁易懂,对我们深入了解vue有一定的帮助,需要的可以了解下
    2023-08-08
  • vue运行环境搭建全过程

    vue运行环境搭建全过程

    这篇文章主要介绍了vue运行环境搭建全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • vue中控制mock在开发环境使用,在生产环境禁用方式

    vue中控制mock在开发环境使用,在生产环境禁用方式

    这篇文章主要介绍了vue中控制mock在开发环境使用,在生产环境禁用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • vue如何实现本项目页面之间跳转

    vue如何实现本项目页面之间跳转

    这篇文章主要介绍了vue如何实现本项目页面之间跳转,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • 如何根据业务封装自己的功能组件

    如何根据业务封装自己的功能组件

    这篇文章主要介绍了Vue封装功能组件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • vue3使用reactive赋值后页面不改变

    vue3使用reactive赋值后页面不改变

    本文主要介绍了vue3使用reactive赋值后页面不改变,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Vue3中进行二维码的生成与解码实现详解

    Vue3中进行二维码的生成与解码实现详解

    这篇文章主要为大家介绍了Vue3中进行二维码的生成与解码实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • vue-cli2 构建速度优化的实现方法

    vue-cli2 构建速度优化的实现方法

    这篇文章主要介绍了vue-cli2 构建速度优化的实现方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • Vue中computed(计算属性)和watch(监听属性)的用法及区别说明

    Vue中computed(计算属性)和watch(监听属性)的用法及区别说明

    这篇文章主要介绍了Vue中computed(计算属性)和watch(监听属性)的用法及区别说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • vue路由拦截及页面跳转的设置方法

    vue路由拦截及页面跳转的设置方法

    这篇文章主要介绍了vue路由拦截及页面跳转的设置方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-05-05

最新评论