vue3中父子组件的双向绑定defineModel详细使用方法

简介: vue3中父子组件的双向绑定defineModel详细使用方法

一、defineProps() 和 defineEmits()

组件之间通讯,通过 props 和 emits 进行通讯,是单向数据流,

子组件不能改变父组件传递给它的 prop 属性,推荐的做法是它抛出事件,通知父组件自行改变绑定的值。

为了在声明 props 和 emits 选项时获得完整的类型推导支持,我们可以使用 defineProps 和 defineEmits API,它们将自动地在 <script setup> 中可用:

  • 父组件:
<template>
  <div>
    <ChildMy v-model:count="count" />
    {{ count }}
  </div>
</template>

<script setup>
  import ChildMy from './child.vue'
  import { ref } from 'vue' 
  const count = ref(1)
</script>
  • 子组件:
<template>
    <div>
        {{ props.count }}
        <button @click="updatedCount">child btn</button>
    </div>
</template>

<script setup>
const props = defineProps(["count"]);
const emit = defineEmits(["update:count"]);

const updatedCount = () => {
    emit('update:count', props.count + 1)
}
</script>
  • defineProps 和 defineEmits 都是只能在


二、defineModel() 的双向绑定

这个宏可以用来声明一个双向绑定 prop,通过父组件的 v-model 来使用。

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


defineModel() 的双向绑定是在编译之后,创建了一个model的ref变量以及一个modelValue的props,并且watch了props中的modelValue;当子组件中的modelValue更新时,会触发update:modelValue事件,当父组件接收到这个事件时候,同时更新父组件的变量。

2.1、基础示例
  • 父组件:
<template>
  <div>
    <ChildMy v-model="message"/>
    {{ message }}
  </div>
</template>

<script setup>
  import ChildMy from './child.vue'
  import { ref } from 'vue' 
  const message = ref('hello')
</script>
  • 子组件:
<template>
    <div>
        {{ message }}
        <button @click="updatedMsg">child btn</button>
    </div>
</template>

<script setup>
const message = defineModel()

const updatedMsg = () => {
    message.value = `world`
}
</script>
2.2、定义类型
  • 子组件:
<template>
    <div>
        {{ message }}
        <button @click="updatedMsg">child btn</button>
    </div>
</template>

<script setup>
const message = defineModel({ type: String })

const updatedMsg = () => {
    message.value = `world`
}
</script>
2.3、声明prop名称
  • 父组件:
<template>
  <div>
    <ChildMy v-model:count="count"/>
    {{ count }}
  </div>
</template>

<script setup>
  import ChildMy from './child.vue'
  import { ref } from 'vue' 
  const count = ref(1)
</script>
  • 子组件:
<template>
    <div>
        {{ count }}
        <button @click="updatedCount">child btn</button>
    </div>
</template>

<script setup>
const count = defineModel("count")
const updatedCount = () => {
    count.value ++
}
</script>
2.4、其他声明
  • 子组件:
<template>
    <div>
        {{ count }}
        <button @click="updatedCount">child btn</button>
    </div>
</template>

<script setup>
const count = defineModel("count", { type: Number, default: 0 , required: true})
const updatedCount = () => {
    count.value ++
}
</script>
2.5、绑定多个值
  • 父组件:
<template>
  <div>
    <ChildMy v-model:count="count" v-model:person="person" />
    {{ person }} - {{ count }}
  </div>
</template>

<script setup>
import ChildMy from './components/child.vue'
import { ref,reactive  } from 'vue'
const count = ref(1)
const person = reactive ({
    name: 'Lucy',
    age: 11
  })
</script>
  • 子组件:
<template>
    <div>
        {{ person }} - {{ count }}
        <button @click="updatedData">child btn</button>
    </div>
</template>

<script setup>
const person = defineModel("person")
const count = defineModel("count")

const updatedData = () => {
    count.value ++
    person.value.age = 22
    person.value.name = "lilei"
}
</script>
2.6、修饰符和转换器

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

const [modelValue, modelModifiers] = defineModel()

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

  • 父组件:
<template>
  <div>
    <ChildMy v-model.trim="message"/>
    {{ message }}
  </div>
</template>

<script setup>
  import ChildMy from './child.vue'
  import { ref } from 'vue' 
  const message = ref(' hello ')
</script>
  • 子组件:
<template>
    <div>
        {{ message }}
        <button @click="updatedMsg">child btn</button>
    </div>
</template>

<script setup>
const [message, modelModifiers] = defineModel({
  set(value) {
    if (modelModifiers.trim) {
       value=value?.trim()
    }
    return value
  }
})

const updatedMsg = () => {
    message.value += ` world`
}
</script>
2.7、修饰符串联
  • 父组件:
<template>
  <div>
    <ChildMy v-model.trim.lowercase="message"/>
    {{ message }}
  </div>
</template>

<script setup>
  import ChildMy from './child.vue'
  import { ref } from 'vue' 
  const message = ref('Hello')
</script>
  • 子组件:
<template>
    <div>
        {{ message }}
        <button @click="updatedMsg">child btn</button>
    </div>
</template>

<script setup>
const [message, modelModifiers] = defineModel({
  get(value) {
    if (modelModifiers.trim) {
        value=value?.trim()
    }
    if (modelModifiers.lowercase) {
        value=value?.toLowerCase();
    }
    return value
  },
  set(value) {
    if (modelModifiers.trim) {
        value=value?.trim()
    }
    if (modelModifiers.lowercase) {
        value=value?.toLowerCase();
    }
    return value
  }
})

const updatedMsg = () => {
    message.value += `World`
}
</script>
目录
相关文章
|
5天前
|
缓存 JavaScript UED
Vue3中v-model在处理自定义组件双向数据绑定时有哪些注意事项?
在使用`v-model`处理自定义组件双向数据绑定时,要仔细考虑各种因素,确保数据的准确传递和更新,同时提供良好的用户体验和代码可维护性。通过合理的设计和注意事项的遵循,能够更好地发挥`v-model`的优势,实现高效的双向数据绑定效果。
107 64
|
5天前
|
JavaScript 前端开发 API
Vue 3 中 v-model 与 Vue 2 中 v-model 的区别是什么?
总的来说,Vue 3 中的 `v-model` 在灵活性、与组合式 API 的结合、对自定义组件的支持等方面都有了明显的提升和改进,使其更适应现代前端开发的需求和趋势。但需要注意的是,在迁移过程中可能需要对一些代码进行调整和适配。
|
27天前
|
JavaScript 数据管理 Java
在 Vue 3 中使用 Proxy 实现数据双向绑定的性能如何?
【10月更文挑战第23天】Vue 3中使用Proxy实现数据双向绑定在多个方面都带来了性能的提升,从更高效的响应式追踪、更好的初始化性能、对数组操作的优化到更优的内存管理等,使得Vue 3在处理复杂的应用场景和大量数据时能够更加高效和稳定地运行。
43 1
|
27天前
|
JavaScript 开发者
在 Vue 3 中使用 Proxy 实现数据的双向绑定
【10月更文挑战第23天】Vue 3利用 `Proxy` 实现了数据的双向绑定,无论是使用内置的指令如 `v-model`,还是通过自定义事件或自定义指令,都能够方便地实现数据与视图之间的双向交互,满足不同场景下的开发需求。
47 1
|
JavaScript
vue父子组件及非父子组件通信
vue父子组件及非父子组件通信
120 0
vue父子组件及非父子组件通信
|
JavaScript
vue父子组件通信以及非父子组件通信的方法
vue父子组件通信以及非父子组件通信的方法
139 0
vue父子组件通信以及非父子组件通信的方法
|
存储 JavaScript
Vue父子组件通信(父级向子级传递数据、子级向父级传递数据、Vue父子组件存储到data数据的访问)
Vue父子组件通信(父级向子级传递数据、子级向父级传递数据、Vue父子组件存储到data数据的访问)
243 0
Vue父子组件通信(父级向子级传递数据、子级向父级传递数据、Vue父子组件存储到data数据的访问)
|
存储 JavaScript
总结Vue第二天:自定义子组件、父子组件通信、插槽
总结Vue第二天:自定义子组件、父子组件通信、插槽
209 0
总结Vue第二天:自定义子组件、父子组件通信、插槽
|
JavaScript
Vue 通过props实现父子组件通信
本文目录 1. 前言 2. 开发新闻列表父组件 3. 开发新闻内容子组件 4. 小结
128 0
|
JavaScript
Vue 父子组件间的通信
前言 在 Vue 项目中父子组件的通信是非常常见的,最近做项目的时候发现对这方面的知识还不怎么熟练,在这边做一下笔记,系统学习一下吧。
1029 0