默认情况

 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>

Logo

前往低代码交流专区

更多推荐