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
}
相关推荐
Dolphin_海豚3 分钟前
前端工程化总览
前端·架构·前端工程化
前端进阶者8 分钟前
webRtc之本地预览摄像头设备绿屏问题
前端
_未完待续8 分钟前
框架实战指南-元素参考
前端·vue.js
JarvanMo12 分钟前
救救我的Android app吧
前端
南岸月明13 分钟前
为什么你拼命做副业,却还是赚不到钱?
前端
帅夫帅夫16 分钟前
你真的知道怎么用CSS吗?
前端
蓝胖子的小叮当22 分钟前
JavaScript基础(十)对象方法总结
前端·javascript
艾小码1 小时前
AI时代,编程简化:前端开发的范式革命
前端
讨厌吃蛋黄酥1 小时前
🔥 揭秘React魔法:从JSX到表单组件的性能与交互之争!
前端·javascript·react.js
沫小北1 小时前
HarmonyOS Lottie动画库总结
前端·harmonyos