当前位置: 首页 > 知识库问答 >
问题:

vue.js - Vue 3 中父组件与子组件的通信以打开 el-dialog 的最佳方式是什么?

祁远
2024-07-01

父组件打开子组件的el-dialog的方式?

方法一、V-model

// Parent.vue
<script setup lang="ts">
import { ref, version as vueVersion } from 'vue'
import { version as epVersion } from 'element-plus'
import { ElementPlus } from '@element-plus/icons-vue'
import Child from "./Child.vue"
const show = ref(false);
</script>

<template>
  <el-button @click="show=true">show</el-button>
  <Child v-model:show="show" />
</template>
// Child.vue
<script setup>
  import {defineModel} from "vue"
  const show = defineModel("show");
</script>

<template>
  <el-dialog v-model="show">
    This is model
  </el-dialog>
</template>

方法二、ref + defineExpose

// parent.vue
<script setup lang="ts">
import { ref, version as vueVersion } from 'vue'
import { version as epVersion } from 'element-plus'
import { ElementPlus } from '@element-plus/icons-vue'
import Child from "./Child.vue"
const childRef = ref(null);
function open() {
  childRef.value.open();
}
</script>

<template>
  <el-button @click="open()">show</el-button>
  <Child ref="childRef"/>
</template>
// Child.vue
<script setup>
  import {defineModel, ref, onMounted, defineExpose} from "vue"
  const show = ref(false);
  function open() {
    show.value = true;
  }
  defineExpose({open})
</script>

<template>
  <el-dialog v-model="show">
    This is model
  </el-dialog>
</template>
  • 还有其他方式吗?
  • 哪种方法是最好的(或者说最佳实践)?

共有4个答案

小牛23098
2024-07-01

我一直用的是第一种方案,前段时间AI了下,觉得这个回答还不错,可以参考下。

61ddb437351c6e2c2dbd52be19c8fc5.png

莘聪
2024-07-01

主要看业务,我这边业务基本按第二种搞,dialog一般用于详情页展示或者表单填写。提交或者关闭多半都有刷新父组件需求。
父组件ref 与 @ 我个人觉得一眼看过去清晰。

<Child ref="childRef" @getData='xxxx'/>

然后给子组件传递参数,就我个人习惯这样

<el-button @click="open(row.id)">show</el-button>
function open(id) {
      childRef.value.open(id);
}

总之,还是看业务与个人习惯趋向哪种。

长孙逸仙
2024-07-01

如果是封装的通用组件,比如说UI库。那么推荐第一种的方式(使用 props + emit 的思路)。只传入 show 属性,然后再按照具体的情况使用 emit 抛出一些 on-showon-close 等等的事件。

如果是基于UI组件库再次封装的业务弹窗组件,那么我推荐的是类似第二种的方式。子组件暴露出来 open() 方法和 close() 等方法在父级调用,并且在子组件内自己操作修改 show 属性和一些其他业务(在打开弹窗的同时很可能需要配合做一些业务处理,比如说一些表单内组件的初始化操作)。

朱宏爽
2024-07-01

Vue 3 中父组件与子组件的通信以打开 el-dialog 的最佳方式

方法分析

方法一、V-model

在 Vue 3 的 Composition API 中,并没有直接提供 defineModel 这样的API来定义一个响应式属性作为模型(v-model 的实现)。实际上,在子组件中直接使用 v-model:propName 时,Vue 会期望子组件接收一个 propNameprops 并发出一个 update:propName 的事件。

正确的方式 是子组件应该使用 propsemits 来与父组件通信。

// Child.vue
<script setup>
import { defineProps, defineEmits } from 'vue'

const props = defineProps({
  show: Boolean
})

const emit = defineEmits(['update:show'])

function toggleDialog() {
  emit('update:show', !props.show)
}
</script>

<template>
  <el-dialog v-model="props.show">
    <span slot="footer" class="dialog-footer">
      <el-button @click="toggleDialog">取 消</el-button>
      <el-button type="primary" @click="toggleDialog">确 定</el-button>
    </span>
    This is a dialog
  </el-dialog>
</template>

方法二、ref + defineExpose

使用 refdefineExpose 是 Vue 3 Composition API 中推荐的方式来暴露子组件中的方法或属性给父组件。这是父组件直接控制子组件内部状态的一个常用手段。

你的示例 Child.vue 已经展示了这种方式,但父组件中的 open 方法应该调用子组件暴露的 open 方法,而不是直接修改子组件的 show 引用(尽管这在 Vue 3 的 ref 中是可行的,但通常不是最佳实践)。

还有其他方式吗?

是的,还有其他方式可以实现父组件和子组件的通信,例如:

  • 使用 provideinject API 实现依赖注入。
  • 使用 Vuex 或 Pinia 这样的状态管理库。
  • 使用 Event Bus 或 Vue 3 的 mitt 库等发布订阅模式。
  • 使用 Vue Router 的导航守卫等(如果通信与路由相关)。

哪种方法是最好的(或者说最佳实践)?

最佳实践 取决于你的具体需求和上下文。

  • 如果 el-dialog 的显示状态完全由父组件控制,并且你希望子组件是“无状态”的,那么使用 v-model(通过 propsemits 实现)是合适的。
  • 如果子组件需要有自己的状态逻辑,并且父组件需要能够影响这些状态,那么使用 refdefineExpose 是合适的。
  • 如果你的应用状态管理很复杂,考虑使用 Vuex 或 Pinia。

在大多数简单的父子组件通信场景中,使用 v-model(通过 propsemits)或 refdefineExpose 就足够了。选择哪种方式取决于你的具体需求和代码的可读性、可维护性。

 类似资料:
  • 本文向大家介绍Vue.js 父子组件通信的十种方式,包括了Vue.js 父子组件通信的十种方式的使用技巧和注意事项,需要的朋友参考一下 面试官:Vue 中父子组件通信有哪些方式? 自己先想一分钟。 无可否认,现在无论大厂还是小厂都已经用上了Vue.js 框架,简单易上手不说,教程详尽,社区活跃,第三方套件还多。真的是前端开发人员必备技能。而且在面试当中也往往会问到关于 Vue 方面的各种问题,其中

  • vue3中子组件向父组件传值 在传值的时候为什么只能在声明一个方法的时候传递,而不能在定义click的时候传递呢

  • 本文向大家介绍vue2.0父子组件及非父子组件之间的通信方法,包括了vue2.0父子组件及非父子组件之间的通信方法的使用技巧和注意事项,需要的朋友参考一下 1.父组件传递数据给子组件 父组件数据如何传递给子组件呢?可以通过props属性来实现 父组件: 子组件通过props来接收数据: 方式1: 方式2 : 方式3: 这样呢,就实现了父组件向子组件传递数据. 2.子组件与父组件通信 那么,如果子组

  • 本文向大家介绍Vue.js 父子组件通讯开发实例,包括了Vue.js 父子组件通讯开发实例的使用技巧和注意事项,需要的朋友参考一下 vue.js,是一个构建数据驱动的 web 界面的库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。(这是官方的一个解释!) 小编没使用过angularjs,也没使用过react.js,不能详细的说明三者的区别,想了解的话,在官方

  • 本文向大家介绍vuejs父子组件通信的问题,包括了vuejs父子组件通信的问题的使用技巧和注意事项,需要的朋友参考一下 父子组件之间可以通过props进行通信: 组件的定义: 1.创建component类:  2.注册一个tagnme: 局部注册: 模板注意事项:  因为 Vue 就是原生的DOM,所以有些自定义标签可能不符合DOM标准,比如想在 table 中自定义一个 tr,如果直接插入 my

  • Vue3 子组件中利用父组件传递过来的值,这么写对吗? 这里options是父组件传递过来的,子组件中使用了options中的属性,这里直接在setup中返回是可以动态绑定的吗,还是要通过computed或reactive包一下再返回?

  • 如何在Children内部拿到父级的ref? 父级是不同的组件

  • 子组件 在expansion函数中可以直接修改父组件的值,vue也不会报警告,这是被允许的吗?为什么可以正常修改