Vue3 v3.4之前如何实现组件中多个值的双向绑定?

文章探讨了在Vue3的script-setup中,如何使用watch和computed方法实现组件间的双向数据绑定,以及如何通过`$emit`和props实现不同组件间值的同步,以`course-buy.vue`和`base.vue`组件为例进行详细解释。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

官方给的例子是关于el-input的,如下。但是@input不是所有组件标签都有的属性啊,有没有一种通用的办法呢?

<script setup>
defineProps({
  firstName: String,
  lastName: String
})

defineEmits(['update:firstName', 'update:lastName'])
</script>

<template>
  <input
    type="text"
    :value="firstName"
    @input="$emit('update:firstName', $event.target.value)"
  />
  <input
    type="text"
    :value="lastName"
    @input="$emit('update:lastName', $event.target.value)"
  />
</template>

基础代码

以一个Dialog组件为例。我们自己写一个course-buy.vue

<template>
  <el-dialog
    v-model="localValue.dialogVisible"
    title="Warning"
    width="500"
    align-center
  >
    <span>Open the dialog from the center from the screen</span>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="localValue.dialogVisible = false">Cancel</el-button>
        <el-button type="primary" @click="localValue.dialogVisible = false">
          Confirm
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script setup lang="ts">
import {PropType} from "vue";

//对外变量
const props = defineProps({
  dialogVisible: Object as PropType<boolean>,
  courseId: Object as PropType<string | number>,
})
const emit = defineEmits(['update:dialogVisible','update:courseId'])
//本地变量
const localValue = reactive({
  dialogVisible: props.dialogVisible,
  courseId: props.courseId
})

</script>

外部在使用时(假设为base.vue),如下使用

<template>
	<CourseBuy
      v-model:dialog-visible="orderPayParams.dialogVisible"
      v-model:course-id="orderPayParams.courseId"
    />
</template>
<script setup lang="ts">
const orderPayParams = reactive({
  dialogVisible: false,
  courseId: 1
});
</script>

上述代码,course-buy.vue中真正使用的变量是localValue本地变量,localValue的值来自base.vue
但是上述的基础代码,dialogVisiblecourseId的值只能从base.vue流向course-buy.vue
如何实现course-buy.vue本身修改localValue的值后,修改变化同步到base.vue呢?

1. watch

如果要让dialogVisible双向绑定,可以写两个watch互相监听并更新。要实现courseId双向绑定也是同理。

<script setup lang="ts">
import {PropType} from "vue";

//对外变量
const props = defineProps({
  dialogVisible: Object as PropType<boolean>,
  courseId: Object as PropType<string | number>,
})
const emit = defineEmits(['update:dialogVisible','update:courseId'])
//本地变量
const localValue = reactive({
  dialogVisible: props.dialogVisible,
  courseId: props.courseId
})
//值双向绑定
watch(() => props.dialogVisible, (newValue) => {
  localValue.dialogVisible = newValue;
});
watch(() => localValue.dialogVisible, (newValue) => {
  emit('update:dialogVisible', newValue);
});
</script>

2. computed(推荐)

不过使用computed可以更简洁,性能也更好。

<script setup lang="ts">
import {PropType} from "vue";

//对外变量
const props = defineProps({
  dialogVisible: Object as PropType<boolean>,
  courseId: Object as PropType<string | number>,
})
const emit = defineEmits(['update:dialogVisible','update:courseId'])
//本地变量
const localValue = reactive({
  dialogVisible: computed({
    get: () => props.dialogVisible,
    set: (value) => emit('update:dialogVisible', value)
  }),
  courseId: props.courseId
})
</script>

在这里插入图片描述

<think>好的,用户想了解Vue中如何实现组件双向绑定。我需要根据提供的引用内容来整理回答,特别是Vue 2和Vue 3的不同方法。 首先,用户提供的引用里提到了Vue 2的.sync修饰符和Vue 3的自定义v-model,还有defineModel宏。我需要分版本来说明。 在Vue 2中,.sync修饰符是通过事件实现的,子组件发送update:propName事件来更新父组件的数据。需要举例说明,比如子组件如何定义props和触发事件,父组件如何使用.sync。 然后是Vue 3的情况,这里v-model可以带参数,允许双向绑定多个属性。比如v-model:title和v-model:content,这样每个属性都可以独立绑定。同时,Vue 3.4引入了defineModel宏,简化了代码,不需要显式定义props和emit,而是直接使用defineModel返回的ref。需要对比传统方式和defineModel的写法,突出简洁性。 还要注意,Vue 2的.sync不是真正的双向绑定,而Vue 3的v-model在底层也是基于事件和prop的,但语法更灵活。需要强调两者虽然方便,但原理还是单向数据流,只是语法糖。 用户的问题可能还关心不同版本之间的区别,所以需要分点说明Vue 2和Vue 3的不同实现方式,并给出示例代码。可能还需要提到一些注意事项,比如在Vue 3中使用defineModel需要配置构建工具,如vite的插件设置,避免eslint报错。 另外,用户提供的引用中有代码示例,我需要确保回答中的代码格式正确,使用$...$和$$...$$的LaTeX格式,但根据用户指令,代码块应该用三个反引号包裹,所以可能不需要特别处理数学表达式。不过要检查是否有行内数学内容,比如变量名之类的,可能需要用$包裹,但示例中的代码似乎没有数学内容,可能不需要。 最后,生成相关问题,可能需要包括Vue 2和3的区别、优缺点、性能考虑,或者defineModel的具体配置方法等。</think>在Vue实现组件双向绑定主要有以下方式,分为Vue 2和Vue 3两个版本: ### 一、Vue 2实现方式 1. **.sync修饰符**(语法糖) - 父组件通过`.sync`传递prop ```vue <child-component :title.sync="parentTitle"></child-component> ``` - 子组件通过`$emit(&#39;update:propName&#39;)`修改 ```vue <button @click="$emit(&#39;update:title&#39;, newValue)"></button> ``` - 原理:自动监听`update:propName`事件[^1] 2. **传统v-model**(单个绑定) - 父组件使用`v-model` ```vue <child-component v-model="value"></child-component> ``` - 子组件需声明`value` prop和`input`事件 ```javascript props: [&#39;value&#39;], methods: { updateValue(newVal) { this.$emit(&#39;input&#39;, newVal) } } ``` ### 二、Vue 3实现方式 1. **多参数v-model** ```vue <child-component v-model:title="parentTitle" v-model:content="parentContent" ></child-component> ``` 子组件通过`emit(&#39;update:title&#39;)`触发更新 2. **defineModel宏**(3.4+推荐) ```vue <!-- 子组件 --> <script setup> const model = defineModel() </script> ``` - 父组件直接使用`v-model`绑定 - 支持多模型: ```javascript const model1 = defineModel(&#39;modelData1&#39;) const model2 = defineModel(&#39;modelData2&#39;) ``` - 需要配置构建工具开启该特性[^2] $$ \text{双向绑定原理} = \text{Prop向下传递} + \text{Event向上更新} $$ ### 三、注意事项 1. 单向数据流原则依然适用 2. 对象类型数据建议深度监听 3. Vue 3的`defineModel`需在vite配置中启用: ```javascript vue({ script: { defineModel: true } }) ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值