Vue3.4之defineModel的用法

👀 defineModel是vue3.4中正式加入的API的,可以简化组件之间双向绑定的流程。

1.首先回顾一下基于v-modal实现的双向绑定

v-model是vue.js提供的一个语法糖,用于在表单元素和组件之间创建双向数据绑定,即当数据变属性化时,相应的表单元素也会自动更新。

1.1 v-model的写法

v-model的原理:v-bind绑定一个value属性,v-on指令给当前元素绑定事件

父组件:

js 复制代码
<template>
  <Children v-model:count="countNumber"></Children>
</template>

<script setup lang="ts">
import Children from './children.vue'
import {ref} from 'vue'

const countNumber = ref(1) 
</script>

子组件:children

js 复制代码
<template>
  <div>
    {{ props.count }}
    <button @click="updateCount">child</button>
  </div>
</template>

<script setup lang="ts">
const props = defineProps(["count"]);
const emits = defineEmits(['update:count'])

const updateCount = () =>{
  emits('update:count', props.count+1)
}
</script>
1.2 自定义事件写法

父组件:

js 复制代码
<template>
  <Children :count="countNumber" @change="updateVal"></Children>
</template>

<script setup lang="ts">
import Children from './components/HelloWorld.vue'
import {ref} from 'vue'

const countNumber = ref(1) 
const updateVal = (item:number) => {
countNumber.value  = item
}
</script>

子组件:children

js 复制代码
<template>
  <div>
    {{ count }}
    <button @click="updateCount">child</button>
  </div>
</template>

<script setup lang="ts">
const props = defineProps<{
  count: number 
}>()

const emits = defineEmits(['change'])

const updateCount = () =>{
  emits('change', props.count+1)
}
</script>
从vue2开始,vue就是单向数据流,在子组件中是不能直接修改props中的值,由子组件抛出一个事件,由父组件去监听这个事件,再去修改父组件中传递给props的变量。自定义事件的写法更显式,适合复杂逻辑的场景。- v-model写法更简洁,减少了样板代码。

2.defineModel实现数据双向绑定

这个宏可以用来声明一个双向绑定 prop,通过父组件的 v-model 来使用。在底层,这个宏声明了一个 model prop 和一个相应的值更新事件。如果第一个参数是一个字符串字面量,它将被用作 prop 名称;否则,prop 名称将默认为 "modelValue"。在这两种情况下,你都可以再传递一个额外的对象,它可以包含 prop 的选项和 model ref 的值转换选项。

父组件:

js 复制代码
<template>
  <Children v-model:count="countNumber"></Children>
</template>

<script setup lang="ts">
import Children from './children.vue'
import {ref} from 'vue'

const countNumber = ref(1) 
</script>

子组件:

js 复制代码
<template>
  <div>
    {{ count }}
    <button @click="updateCount">child</button>
  </div>
</template>

<script setup lang="ts">
const count = defineModel("count", {
  type: Number,
  default: 0
}) 

const updateCount = () =>{
  count.value++
}
</script>

2.1修饰符和转换器

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

父组件:

js 复制代码
<Children v-model:message.capitalize="word"/>

<script setup lang="ts">
import Children from './children.vue'
import {ref} from 'vue'

const word = ref('test')
</script>

子组件:

js 复制代码
<div>Message: {{ message }}</div>
<input :value="message" @input="handleInput">
<script setup lang="ts">
const [message, modifiers] = defineModel('message', {
    type: String,
    default: 'test',
    set(value){
    if(modifiers.capitalize){
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
    return value
    }
})
const handleInput = (e) => {
  message.value = e.target.value
}
相关推荐
JC_You_Know44 分钟前
多语言网站的 UX 陷阱与国际化实践陷阱清单
前端·ux
Python智慧行囊1 小时前
前端三大件---CSS
前端·css
Jinuss1 小时前
源码分析之Leaflet中Marker
前端·leaflet
成都渲染101云渲染66661 小时前
blender云渲染指南2025版
前端·javascript·网络·blender·maya
聆听+自律1 小时前
css实现渐变色圆角边框,背景色自定义
前端·javascript·css
牛马程序小猿猴2 小时前
17.thinkphp的分页功能
前端·数据库
huohuopro3 小时前
Vue3快速入门/Vue3基础速通
前端·javascript·vue.js·前端框架
草巾冒小子3 小时前
vue3中解决 return‘ inside ‘finally‘ block报错的问题
前端·javascript·vue.js
互联网搬砖老肖3 小时前
Web 架构之高可用基础
前端·架构
zfyljx3 小时前
五子棋html
前端·css·html