【Vue3】使用v-model实现父子组件通信(常用在组件封装规范中)

历史小剧场

历史告诉我们,痞子就算混一辈子,也还是痞子,滑头,最后只能滑自己。长得帅,不能当饭吃。

成大器者的唯一要诀,是能吃亏。

吃亏就是占便宜,原先我不信,后来我信了,相当靠谱。----《明朝那些事儿》

概述

v-mode实现父子组件数据同步原理主要分为:

  • 父组件添加modelValue绑定数据且传递到子组件,然后绑定@update:modelValue事件接收子组件传过来的值
  • 子组件内部使用defineProps来接收父组件modelValue传过来的值,使用defineEmits自定义事件修改值然后触发父组件@update绑定的事件

同步单个数据

父组件

js 复制代码
<!--  -->
<template>
    <div>

        <!-- v-model用在HTML上 -->
        <!-- <input type="text" v-model="username"> -->
        <!-- <input type="text" :value="username" @input="username = (<HTMLInputElement>$event.target)!.value" /> -->

        <h4>账号: {{ username }}</h4>
        <h4>密码: {{ pwd }}</h4>
        <!-- v-model用在自定义组件上 -->
        <!-- <XinchaoInput v-model:username="username" v-model:pwd="pwd" /> -->
        <XinchaoInput 
        :username="username"
        @update:username="username = $event" />
    </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';
import XinchaoInput from './XinchaoInput.vue';


const username = ref<string>("张三")
const pwd = ref<string>("123131")
watch(username, (oldValue, newValue) => {
    console.log(newValue)
})
</script>

<style lang="scss" scoped>

</style>

子组件

js 复制代码
<!--  -->
<template>
    <div>
        <input type="text"
        :value="username"
        @input="emit('update:username', (<HTMLInputElement>$event.target)!.value)" />
        <!-- <br>
        <input type="text"
        :value="pwd"
        @input="emit('update:pwd', (<HTMLInputElement>$event.target)!.value)" /> -->
    </div>
</template>

<script setup lang="ts">
defineProps(['username', 'pwd'])
const emit = defineEmits(['update:username', 'update:pwd'])

</script>

<style lang="scss" scoped>
input {
    border: 2px solid #ccc;
    border-radius: 5px;
    padding: 2px;
    background-color: darkcyan;
    color: white;
}
</style>

同步多个数据

父组件

js 复制代码
<!--  -->
<template>
    <div>

        <!-- v-model用在HTML上 -->
        <!-- <input type="text" v-model="username"> -->
        <!-- <input type="text" :value="username" @input="username = (<HTMLInputElement>$event.target)!.value" /> -->

        <h4>账号: {{ username }}</h4>
        <h4>密码: {{ pwd }}</h4>
        <!-- v-model用在自定义组件上 -->
        <XinchaoInput v-model:username="username" v-model:pwd="pwd" />
        <!-- <XinchaoInput 
        :username="username"
        @update:username="username = $event" /> -->
    </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';
import XinchaoInput from './XinchaoInput.vue';


const username = ref<string>("张三")
const pwd = ref<string>("123131")
watch(username, (oldValue, newValue) => {
    console.log(newValue)
})
</script>

<style lang="scss" scoped>

</style>

子组件

js 复制代码
<!--  -->
<template>
    <div>
        <input type="text"
        :value="username"
        @input="emit('update:username', (<HTMLInputElement>$event.target)!.value)" />
        <br>
        <input type="text"
        :value="pwd"
        @input="emit('update:pwd', (<HTMLInputElement>$event.target)!.value)" />
    </div>
</template>

<script setup lang="ts">
defineProps(['username', 'pwd'])
const emit = defineEmits(['update:username', 'update:pwd'])

</script>

<style lang="scss" scoped>
input {
    border: 2px solid #ccc;
    border-radius: 5px;
    padding: 2px;
    background-color: darkcyan;
    color: white;
}
</style>
相关推荐
升鲜宝供应链及收银系统源代码服务6 小时前
《IntelliJ + Claude Code + Gemini + ChatGPT 实战配置手册升鲜宝》
java·前端·数据库·chatgpt·供应链系统·生鲜配送
i建模6 小时前
将Edge浏览器的标签页从顶部水平排列**移至左侧垂直侧边栏
前端·edge
跟着珅聪学java6 小时前
js编写中文转unicode 教程
前端·javascript·数据库
英俊潇洒美少年7 小时前
Vue3 深入响应式系统
前端·javascript·vue.js
颜酱7 小时前
回溯算法实战练习(3)
javascript·后端·算法
英俊潇洒美少年8 小时前
React 最核心 3 大底层原理:Fiber + Diff + 事件系统
前端·react.js·前端框架
我命由我123458 小时前
React Router 6 - 概述、基础路由、重定向、NavLink、路由表
前端·javascript·react.js·前端框架·ecmascript·html5·js
LJianK18 小时前
java封装
java·前端·数据库
yaaakaaang8 小时前
(四)前端,如此简单!---Promise
前端·javascript
aini_lovee9 小时前
C# 实现邮件发送源码(支持附件)
开发语言·javascript·c#