【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>
相关推荐
佛系打工仔40 分钟前
绘制K线第二章:背景网格绘制
android·前端·架构
计算机毕设VX:Fegn08952 小时前
计算机毕业设计|基于springboot + vue医院设备管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
明天好,会的2 小时前
分形生成实验(五):人机协同破局--30万token揭示Actix-web状态管理的微妙边界
运维·服务器·前端
C_心欲无痕3 小时前
nginx - alias 和 root 的区别详解
运维·前端·nginx
北辰alk3 小时前
Vue 路由信息获取全攻略:8 种方法深度解析
vue.js
北辰alk3 小时前
Vue 三剑客:组件、插件、插槽的深度辨析
vue.js
北辰alk3 小时前
Vue Watch 立即执行:5 种初始化调用方案全解析
vue.js
北辰alk3 小时前
Vue 组件模板的 7 种定义方式:从基础到高级的完整指南
vue.js
北辰alk3 小时前
深入理解 Vue 生命周期:created 与 mounted 的核心差异与实战指南
vue.js