Vue 3.4 新增 的 defineModel()

1,516 阅读1分钟

defineModel()

这个宏可用于声明一个双向绑定的属性,可以通过在父组件中使用 v-model 进行消费。在“组件 v-model 指南”中也讨论了示例用法。

在底层,这个宏声明了一个模型属性(model prop)和一个相应的值更新事件。如果第一个参数是一个字面字符串,它将被用作属性名;否则,属性名将默认为 "modelValue"。在这两种情况下,你还可以传递一个额外的对象,该对象可以包含属性的选项以及模型引用的值转换选项。

// declares "modelValue" prop, consumed by parent via v-model
const model = defineModel();
// OR: declares "modelValue" prop with options
const model = defineModel({ type: String });

// emits "update:modelValue" when mutated
model.value = "hello";

// declares "count" prop, consumed by parent via v-model:count
const count = defineModel("count");
// OR: declares "count" prop with options
const count = defineModel("count", { type: Number, default: 0 });

function inc() {
  // emits "update:count" when mutated
  count.value++;
}

修饰符和转换器

要访问与 v-model 指令一起使用的修饰符,我们可以像这样解构 defineModel() 的返回值:

const [modelValue, modelModifiers] = defineModel();

// corresponds to v-model.trim
if (modelModifiers.trim) {
  // ...
}

当存在修饰符时,我们可能需要在读取值或将其同步回父级时进行值的转换。我们可以通过使用 getset 转换器选项来实现这一点:

const [modelValue, modelModifiers] = defineModel({
  // get() omitted as it is not needed here
  set(value) {
    // if the .trim modifier is used, return trimmed value
    if (modelModifiers.trim) {
      return value.trim();
    }
    // otherwise, return the value as-is
    return value;
  },
});

与 TypeScript 一起使用

类似于 definePropsdefineEmitsdefineModel 也可以接收类型参数,用于指定模型值和修饰符的类型:

const modelValue = defineModel<string>()
//    ^? Ref<string | undefined>

// default model with options, required removes possible undefined values
const modelValue = defineModel<string>({ required: true })
//    ^? Ref<string>

const [modelValue, modifiers] = defineModel<string, 'trim' | 'uppercase'>()
//                 ^? Record<'trim' | 'uppercase', true | undefined>