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
}
相关推荐
浩星6 分钟前
electron系列5:深入理解Electron打包
前端·javascript·electron
患得患失94911 分钟前
【前端WebSocket】心跳功能,心跳重置策略、双向确认(Ping-Pong) 以及 指数退避算法(Exponential Backoff)
前端·websocket·算法
英俊潇洒美少年13 分钟前
React 实现 AI 流式打字机对话:SSE 分包粘包处理 + 并发优化
前端·javascript·react.js
chQHk57BN15 分钟前
前端测试入门:Jest、Cypress等测试框架使用教程
前端
遇见你...24 分钟前
前端技术知识点
前端
AC赳赳老秦36 分钟前
OpenClaw image-processing技能实操:批量抠图、图片尺寸调整,适配办公需求
开发语言·前端·人工智能·python·深度学习·机器学习·openclaw
We་ct43 分钟前
LeetCode 172. 阶乘后的零:从暴力到最优,拆解解题核心
开发语言·前端·javascript·算法·leetcode·typescript
军军君0143 分钟前
数字孪生监控大屏实战模板:可视化数字统计展示
前端·javascript·vue.js·typescript·echarts·数字孪生·前端大屏
此刻觐神1 小时前
IMX6ULL开发板学习-03(Linux文件相关命令)
前端·chrome
吴声子夜歌1 小时前
ES6——Iterator和for...of循环详解
前端·javascript·es6