Vue3中组件通讯的方式

Vue3中组件通讯的方式

1 🤖GPT🤖: (答案有点问题混淆了vue2的内容)

父组件向子组件传递数据

  1. props 子组件通过 props 属性从父组件接收数据。
  2. emit事件子组件通过emit 事件 子组件通过 emit事件子组件通过emit 发射事件向父组件发送消息。
  3. provide / inject 父组件通过 provide 提供数据,子组件通过 inject 注入数据。
  4. ref 父组件通过 ref 获取子组件实例,然后调用子组件的方法。
  5. Slots 在父组件中使用Slots向子组件传递内容,子组件可以通过$slots来获取这些内容,并将它们渲染到自己的视图中。

子组件向父组件传递数据

emit事件使用emit 事件 使用 emit事件使用emit 发射事件,父组件通过 v-on 监听该事件。

provide/inject 子组件通过 inject 注入父组件提供的数据,然后触发 Action 修改该数据,父组件的数据也就变了。

Ref 父组件通过 ref 获取子组件的实例,子组件调用 ref 内容,父组件监听其变化。

Vuex 使用 Vuex 管理共享状态,子组件通过 mutation 或 action 修改状态,父组件监听状态变化。

Event Bus 利用 Vue 的实例作为 EventBus ,子组件通过 Bus.$emit 触发事件,父组件监听该事件的变化。

兄弟组件之间的数据传递

EventBus 可以使用EventBus来创建一个全局的事件总线,从而在兄弟组件之间进行数据传递。通过在兄弟组件中使用emit和emit和emit和on来触发和监听事件,从而实现数据的传递。

Provide 和 Inject Vue 3中的Provide和Inject API也可以用于兄弟组件之间的数据传递,可以通过在父组件中使用Provide来提供数据,然后在兄弟组件中使用Inject来获取这些数据,从而实现兄弟组件之间的数据传递。

Vuex Vuex是Vue 3中的状态管理库,可以用于管理全局的数据状态,从而实现兄弟组件之间的数据传递。

父组件向子组件传递数据:(父传子)

1. props:

逐级透传

父组件

html 复制代码
<template>
	<ChildComponent  :msg="message" />
</template>
<script setup> 
	const message = 'hello'
</script>

子组件:

html 复制代码
<template>
	<p>{{ msg }}</p> 
</template>

<script setup>
	defineProps(['msg'])
</script>

2. provide/inject

跨级共享

provide(提供): 父组件中注册,传递给后代组件的数据对象

inject( 注入):后代组件中接收父组件提供的数据对象

父组件 Root.vue

html 复制代码
<template>
  <div>
    <Footer/>
  </div>
</template>
<script setup>
    import { ref,provide } from 'vue'
    import Footer from './Footer.vue' //导入子组件Footer
    //父组件中注册给共享后代组件的信息
    provide(/* 注入名 */ 'mgs', /* 值 */ '父组件信息!')  
</script>

子组件 Footer.vue

html 复制代码
<template>
    <DeepChild/>
</template>
<script setup>
import DeepChild from './DeepChild.vue' //导入子组件Footer
//在子组件Footer中可以不需要接收父组件Root共享的数据,在后代组件中,直接接收,实现跨级传递
</script>

子孙组件DeepChild.vue

不需要父组件Footer传递,就能跨级获取祖先组件Root传递的数据

html 复制代码
<template>
    <div>
        {{ msg }}
    </div>
</template>
<script setup>
    import { inject } from 'vue'
    const msg = inject('msg') //跨级接收祖先组件的共享的信息
    console.log(msg) //父组件信息
</script>

父组件向子组件传递信息,如果是多层组件嵌套(父>子>孙>孙孙...) ,props逐级透传十分麻烦,props可用但不优雅,更推荐 provide/inject依赖注入的方式;

provide/inject依赖注入中父组件向后代组件通讯,如果说props是传递,逐级透传的,那么依赖注入更准确来说是在父组件中与后代组件共享数据,可实现跨级共享;

3. 透传 Attributes(非props和非emit)

"透传 attribute"指的是传递给一个组件,却没有被该组件声明为 props 或 emits 的 attribute 或者 v-on 事件监听器。最常见的例子就是 class、style 和 id

作用: 在父组件标签上声明的参数/事件监听,会透传到子组件中

3.1 Attributes透传参数

父组件

html 复制代码
<!-- 透传参数class到子组件中 -->
<MyButton class="large" />

子组件 MyButton.vue

html 复制代码
<button>click me</button>

最终渲染的html标签

html 复制代码
<button class="btn large">click me</button>
3.2 Attributes透传事件监听(有点像冒泡事件)

父组件

html 复制代码
 <!-- 透传参数class到子组件中 -->
 <MyButton @click="onClick1"  />
 
 <script setup>
     import  MyButton from './MyButton.vue'
     const onClick = ()=>{
       cosole.log("透传事件监听,从父组件触发")
     }
 </script>

子组件 MyButton.vue

html 复制代码
<button @click ="onClick2">click me</button>

当点击子组件的按钮时:

父组件的onClick1 和子组件的onClick2 都触发

3.3 useAttrs 像defineProps获取透传Attributes

父组件

html 复制代码
<!-- 透传参数ms到子组件中 -->
<Child  msg="父组件中传递数据"  />

<script setup>
    import  Child from './child.vue'
</script>

子组件child.vue

html 复制代码
 <script setup>
import { useAttrs } from 'vue'
//useAttrs像defineProps获取透传Attributes
const attrs = useAttrs()
cosole.log(attrs.msg) //父组件中传递数据
</script>

4. slot 插槽

父组件向子组件指定位置插入html内容渲染

4.1 默认插槽(传递html/组件)

父组件

html 复制代码
<template>
  <Child>
    <div>插入的html,将会在子组件中指定slot的位置渲染出来</div>
  </Child>
</template>

子组件

html 复制代码
<template>
   <slot><slot/>
</template>
4.2 具名插槽(父->子)

当需要渲染不同的内容时,默认插槽显然不够用,需要按插槽的name名进行区别渲染

父组件

#XX == v-slot:XX 这2个写法都是插槽name名在父组件的写法

html 复制代码
<子>
  <template #XX1> 插槽1 </template>
  <template v-slot:XX2>插槽2</template>
</子>

子组件

html 复制代码
<template>
   <slot name="XX1"><slot/>
   <slot name="XX2"><slot/>  
</template>
4.3 作用域插槽 (子>父)

作用插槽分为: 默认作用域插槽和 具名作用域插槽

elementUI中table组件插入按钮就是使用了默认作用域插槽

4.3.1. 默认作用域插槽: v-slot:defalut = #defalut = v-slot

父组件

html 复制代码
<子>
  <template #default="slotProps">
      {{slotProps.XX}}
  </template>
</子>

子组件

html 复制代码
<slot :XX="子组件数据"></slot>
4.3.2. 具名作用域插槽

父组件

html 复制代码
 <子>
  <template #slotName="slotProps">
      {{slotProps.XX}}
  </template>
</子>

子组件

html 复制代码
<slot name="slotName"  :XX="子组件数据"></slot>

Element-PlusUI组件框架中table组件

table组件中就用到了作用域插槽

html 复制代码
<el-table :data="tableData" style="width: 100%" max-height="250">
  <el-table-column fixed prop="date" label="Date" width="150" />
  <el-table-column fixed="right" label="Operations" width="120">
    <template #default="scope">
        {{scope.row.date}}
    </template>
  </el-table-column>
</el-table>

子组件向父组件传递数据:(子传父)

1.组件事件emit

父组件中v-on(简写@)监听

子组件中$emit触发

父组件

父组件中v-on(简写@)监听

html 复制代码
 <template>
  <child @some-event="callback" />
</template>
<script setup>
import child from './child.vue'
const callback = (target) => {
  console.log('父组件-callback ')
  console.log(target) //子组件传递的数据
}
</script>

子组件

子组件中$emit触发

html 复制代码
 <templete>
  <!-->在templete中使用$emit触发,不需要defineEmits声明</-->    
  <button @click="$emit('someEvent', '子组件传递的数据')">click me</button>  
    <!-->触发方法中的emit,需要defineEmits声明</-->      
   <button @click="buttonClick()">click me</button>  
</templete>

<script setup>
//setup语法糖中显示声明emit    
const emit = defineEmits(['someEvent'])
function buttonClick() {
  //触发emit  
  emit('someEvent', '子组件传递的数据')
}
</script>

2. defineExpose/ ref

子组件中通过defineExpose向外暴露数据或方法

父组件中通过ref获取子组件暴露的数据或调用子组件的方法

父组件

在父组件中需要声明子组件的ref, 如:const childRef = ref()

html 复制代码
 <template>
  <child ref="childRef" />
</template>
<script setup>
import { ref, onMounted } from 'vue'
// 引入子组件
import child from './child.vue'
    
const childRef = ref()
onMounted(() => {
  console.log(childRef.value.data1) // 子组件数据
  childRef.value.fn() // 子组件中的方法
})
</script>

子组件

子组件中通过defineExpose向外暴露数据或方法

html 复制代码
 <script setup>
import { ref } from 'vue'
const data1 = ref('子组件数据')
const fn = () => {
  console.log('子组件中的方法')
}
//通过defineExpose向外暴露数据或方法
defineExpose({
  data1,
  fn
})
</script>

跨组件通讯-全局状态共享(状态管理库): Vuex /Pinia

在Vue3已经逐渐用Pinia这个菠萝替代Vuex了

Pinia,官方文档描述:符合直觉的 Vue.js 状态管理库 hook的写法!

其实Pinia的官方文档就写得很清楚了:🛬🛬🛬🛬🛬🛬🛬🛬🛬🛬🛬🛬为什么你应该使用 Pinia?

相关推荐
小小竹子几秒前
前端vue-实现富文本组件
前端·vue.js·富文本
万物得其道者成8 分钟前
React Zustand状态管理库的使用
开发语言·javascript·ecmascript
小白小白从不日白9 分钟前
react hooks--useReducer
前端·javascript·react.js
下雪天的夏风21 分钟前
TS - tsconfig.json 和 tsconfig.node.json 的关系,如何在TS 中使用 JS 不报错
前端·javascript·typescript
青稞儿27 分钟前
面试题高频之token无感刷新(vue3+node.js)
vue.js·node.js
diygwcom33 分钟前
electron-updater实现electron全量版本更新
前端·javascript·electron
volodyan36 分钟前
electron react离线使用monaco-editor
javascript·react.js·electron
^^为欢几何^^1 小时前
lodash中_.difference如何过滤数组
javascript·数据结构·算法
Hello-Mr.Wang1 小时前
vue3中开发引导页的方法
开发语言·前端·javascript
程序员凡尘1 小时前
完美解决 Array 方法 (map/filter/reduce) 不按预期工作 的正确解决方法,亲测有效!!!
前端·javascript·vue.js