vue3新引入的defineModel你用了吗?巨好用!

defineModel 是 Vue 3.4+ 中引入的一个新特性,用于声明组件的 v-model 双向绑定的 prop,并简化了父子组件之间的双向数据绑定过程。它允许在组件中创建双向绑定的 prop,并自动处理 modelValue 和更新事件(update:modelValue)。

为什么需要 defineModel

在 Vue 3 中,v-model 默认会绑定到 modelValue 属性,同时要求组件触发一个名为 update:modelValue 的事件来进行更新。这种写法虽然能够工作,但对于某些场景来说比较繁琐。

defineModel 的引入简化了这个过程,并允许你定义具有 v-model 功能的属性(不仅限于 modelValue),并能够为该属性提供默认值、类型和其他选项。

语法

defineModel() 可以接受两个参数:

  1. 第一个参数:string 或者不传递
    • 如果是字符串,它将用作 prop 名称(默认是 modelValue)。
    • 如果没有传入参数,则默认使用 modelValue
  2. 第二个参数:对象选项
    • 可以包含 typedefaultrequired 等字段来为 modelValue 提供更多的配置。

示例 1:基础用法

父组件

<template>
  <Counter v-model="count" />
</template>

<script setup>
import { ref } from 'vue';
import Counter from './Counter.vue';

const count = ref(0); // 父组件绑定的值
</script>

子组件

<script setup>
const count = defineModel();
</script>

<template>
  <div>{{ count.value }}</div>
</template>

该组件会拥有一个 modelValue 属性,并且当值发生变化时,会触发 update:modelValue 事件。

示例 2:带有默认值和类型检查的 defineModel

父组件

<template>
  <Counter v-model="count" />
</template>

<script setup>
import { ref } from 'vue';
import Counter from './Counter.vue';

const count = ref(0); // 父组件绑定的值
</script>

子组件

<script setup>
import { defineModel } from 'vue';

const modelValue = defineModel({
  type: Number,
  default: 0,
  required: true,
});

function increment() {
  modelValue.value++; // 直接修改值,自动触发 "update:modelValue" 事件
}
</script>

<template>
  <div>
    <button @click="increment">Increment</button>
    <p>Value: {{ modelValue }}</p>
  </div>
</template>

上面的代码定义了一个类型为 String 且默认值为 'Hello World'modelValue

示例 3:多个 v-model(使用自定义名称)

父组件

<template>
  <Counter v-model:count="count" />
</template>

<script setup>
import { ref } from 'vue';
import Counter from './Counter.vue';

const count = ref(0); // 父组件绑定的值
</script>

子组件

<script setup>
const count = defineModel('count', { type: Number, default: 0 });
</script>

<template>
  <div>{{ count.value }}</div>
</template>

通过传入字符串 'count',组件会使用 v-model:count 来进行双向绑定。

defineModel 的实用场景

defineModel 在需要处理多个双向绑定的 prop 时特别有用。例如,某些组件可能需要处理多个属性的双向绑定,你可以为每个属性创建一个 defineModel 来替代手动管理 v-model 和事件的繁琐步骤。

特别注意

  1. v-model 的修饰符:如果你使用了 v-model.trimv-model.lazy 等修饰符,你可以通过 defineModel 的选项来处理这些修饰符,并对 modelValue 的值进行转换(例如去除空格、延迟更新等)。
  2. 双向绑定的限制defineModel 仅用于声明父子组件之间的双向绑定,但父组件必须通过 v-model 绑定值,子组件则使用 defineModel 来接收这个值并更新它。

修饰符和转换器

为了获取 v-model 指令使用的修饰符,我们可以像这样解构 defineModel() 的返回值:

const [modelValue, modelModifiers] = defineModel()

// 对应 v-model.trim
if (modelModifiers.trim) {
  // ...
}

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

const [modelValue, modelModifiers] = defineModel({
  // get() 省略了,因为这里不需要它
  set(value) {
    // 如果使用了 .trim 修饰符,则返回裁剪过后的值
    if (modelModifiers.trim) {
      return value.trim()
    }
    // 否则,原样返回
    return value
  }
})

总结

defineModel 的主要作用是简化 Vue 3 组件的 v-model 使用,它让你能够更轻松地管理组件的双向绑定,自动处理 modelValueupdate:modelValue,并允许自定义绑定名称和提供类型、默认值等选项。

通过 defineModel,你可以让父子组件之间的双向数据绑定变得更加简洁和高效。

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容