Skip to content
导航栏

你不知道的defineModel

作者:Kano Zhao
发表于:2023-06-20
更新于:1 年前

相信大伙都已经收到Vue3.3最新版的风了吧,新版本的更新中优化了不少此前在Vue3中比较“麻烦”的使用方法,下面是更新的简介图 👇

defineModel

DefineModel核心

defineModel 这是一个语法糖,目前需要手动开启,否则无法识别。

js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue({
    script: {
      defineModel: true,
      propsDestructure: true // 解构 props
    }
  })],
})

新旧对比

以前组件想要支持 v-model,需要两个步骤:

  • 声明 props
  • 在打算更新 props 时,emit update:propName 事件

子组件支持 v-model 的写法:

vue
<!-- BEFORE  -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
console.log(props.modelValue)

function onInput(e) {
  emit('update:modelValue', e.target.value)
}
</script>

<template>
  <input :value="modelValue" @input="onInput" />
</template>

父组件:

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

const msg = ref('')
</script>
<template>
  <Comp v-model="msg">
</template>

Vue 3.3 用新的 defineModel 宏简化了用法。宏将自动注册 props 和事件 ,并返回一个 ref:

vue
<!-- AFTER -->
<script setup>
const modelValue = defineModel()
console.log(modelValue.value)
</script>

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

根据接受 defineModel 返回值的变量名,这里是 modelValue,会自动定义 props 名为 modelValue,emit 事件为 update:modelValue

也支持显示传入 props 名称

js
const count = defineModel<number>('count', { default: 0 })

此功能是实验性的,需要明确的选择加入

详情:RFC#503-[Core Team RFC] New SFC macro: defineModel #503
https://github.com/vuejs/rfcs/discussions/503
原文地址:Today we're excited to announce the release of Vue 3.3 'Rurouni Kenshin'
https://blog.vuejs.org/posts/vue-3-3

相信看完上面的案例之后大伙就已经有一个大概的猜想了:

DefineModel 其实为组件实例注册了 update:modelValue 事件,并且在 propssetter 中又调用了 update:modelValue 事件,从而实现的 v-model 语法糖

上面的猜测又包含了两个问题:

  1. defineModel 是如何注册 update:modelValue 事件的
  2. 如何在 defineModel 变量修改时发布 update:modelValue 事件的

Contributors

Kano Zhao