vue 组件上使用v-model以实现双向绑定

默认情况

 v-model 实际上就是 $emit('input') 以及 props:value 的组合语法糖,只要组件中满足这两个条件,就可以在组件中使用 v-model

父组件调用子组件,通过v-model绑定属性值,在子组件中默认接收props为modelValue ,子组件中触发更新需要通过emit 触发update:modelValue自定义事件。

// 父组件调用子组件
<SubInput
  v-model="formState.title0"
/>
// 子组件
<input :value="modelValue" @input="($event: any) => $emit('update:modelValue', $event.target.value)" />
 
 props: {
    modelValue: { type: String, require: true }
  },
 emit: ['update:modelValue'],

传参

默认情况下,v-model 在组件上都是使用 modelValue 作为 prop,并以 update:modelValue 作为对应的事件。我们可以通过给 v-model 指定一个参数来更改这些名字:

在这个例子中,子组件应声明一个 title prop,并通过触发 update:title 事件更新父组件值:

// 父组件调用子组件
<SubInput v-model:title1="formState.title1" />
 
// 子组件
<input :value="title1" @input="($event: any) => $emit('update:title1', $event.target.value)" />
 
 props: {
    title1: { type: String, require: true },
  },
  emit: [ 'update:title1'],

v-model 修饰符

组件的 v-model 上所添加的修饰符,可以通过 modelModifiers prop 在组件内访问到。在下面的组件中,我们声明了 modelModifiers 这个 prop,它的默认值是一个空对象。

对于又有参数又有修饰符的 v-model 绑定,生成的 prop 名将是 arg + "Modifiers"

// 父组件调用子组件
<SubInput
    v-model.capitalize="formState.title0"
    v-model:title2.capitalize="formState.title2"
/>
// 子组件
<input :value="title2" @input="handleTitle2"  />
 
 props: {
    modelModifiers:  { default: () => ({}) },
    title2Modifiers:  { default: () => ({capitalize: false}) },
  },
// 对于传递了capitalize修饰符的输入进行自动转换首字母大写的处理
const handleTitle2 = (e: any) => {
      let value = e.target.value;
      if (props.title2Modifiers.capitalize) {
        value = value.charAt(0).toUpperCase() + value.slice(1)
      }
      emit('update:title2', value)
}
onMounted(() => {
      // 无参数有修饰符生成的prop名:modelModifiers
      console.log('modelModifiers: ' , props.modelModifiers)
      // 有参数且有修饰符生成的 prop名:arg + "Modifiers"
      console.log('title2Modifiers: ', props.title2Modifiers)
})

使用一个可写的,同时具有 getter 和 setter 的 computed 属性

// 父组件
<SubSelect v-model="formState.province" />
// 子组件
<template>
  <a-divider orientation="right">使用一个可写的,同时具有 getter 和 setter 的 computed 属性</a-divider>
  <div>省份:</div>
  <a-select
    v-model:value="value"
    show-search
    allowClear
    placeholder="input"
    :style="{ width: '200px' }"
    :options="provinces"
    :filter-option="filterOption"
  ></a-select>
</template>
 
<script lang="ts">
import { defineComponent, computed } from 'vue';
import { provinces } from '@/utils/consts';
export default defineComponent({
  props: {
    modelValue: { type: String, require: true },
  },
  emit: ['update:modelValue'],
  setup(props, { emit }) {
    const value = computed({
      get() {
        return props.modelValue;
      },
      set(value) {
        emit('update:modelValue', value);
      },
    });
    
    const filterOption = (input: string, option: any) => {
      return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0;
    };
    return {
      filterOption,
      value,
      provinces
    };
  },
});
</script>

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3 中,你可以使用 `v-model` 指令来实现双向绑定组件,但是也可以使用 `emit` 和 `props` 实现同样的效果。 具体来说,你可以在子组件使用 `props` 将父组件的数据传递给子组件,然后在子组件中触发 `emit` 事件来通知父组件更新其数据。下面是一个示例: ```html <!-- Parent.vue --> <template> <div> <h1>Parent Component</h1> <Child :value="name" @input="name = $event" /> <p>My name is {{ name }}</p> </div> </template> <script> import Child from './Child.vue'; export default { components: { Child, }, data() { return { name: 'John', }; }, }; </script> ``` ```html <!-- Child.vue --> <template> <div> <h2>Child Component</h2> <input :value="value" @input="$emit('input', $event.target.value)" /> </div> </template> <script> export default { props: { value: String, }, }; </script> ``` 在这个示例中,父组件 `Parent.vue` 中的 `name` 数据通过 `props` 传递给了子组件 `Child.vue` 中的 `value` 属性。在子组件中,我们使用 `input` 事件触发 `emit`,并传递输入框中的值作为 `$event` 参数。在父组件中,我们使用 `@input` 监听子组件触发的 `input` 事件,并将 `$event` 参数(即子组件中的输入框的值)赋给 `name` 数据,从而实现双向绑定。 需要注意的是,在 Vue 3 中,`v-model` 实际上是一个语法糖,它会自动将父组件中的数据通过 `props` 传递给子组件,并监听子组件的 `update:modelValue` 事件来更新父组件的数据。因此,如果你不想使用 `v-model`,也可以手动实现这个过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值