学习vue3 六,兄弟组件传参,provide/inject

Provide/Inject

通常父组件给子组件传递数据时,使用props的方式,如果是比较深得组件嵌套的话,就需要逐层的进行传递,这样的话,可能会比较麻烦

vue提过了一个api去简化这个操作

provide 可以在祖先组件中指定我们想要提供给后代组件的数据或方法,而在任何后代组件中,我们都可以使用 inject 来接收 provide 提供的数据或方法。 

祖先组件 

<script setup lang="ts">
 // 采用provide的方式,将祖先组件数据传递给子组件
import { provide,ref } from 'vue'
import A from "./components/A.vue"
const count = ref(0)
provide('count',count)
</script>

<template>
  <div>
    <h1>{{count}}</h1>
  </div>
  <A></A>
</template>

<style scoped>

</style>

在需要用到这个ref数据的时候,只需要inject接受即可

也可以采用readonly防止数据被更改

provide('count',readonly(count))

后代组件

<script setup lang="ts">
import {inject} from "vue";
const data = inject('count')
</script>

<template>
  <div class="container">
    <div>
      <span>请输入:</span>
      <input type="text" v-model="data">
    </div>
  </div>
</template>

<style scoped>
.container {
  width: 500px;
  height: 500px;
  background-color: #ccc;
  border: 1px solid grey;
  margin: 0 auto;
}
.header {
  height: 50px;
  background-color: #eee;
  border: 1px solid grey;
}
.body {
  height: 400px;
  background-color: #ddd;
  border: 1px solid grey;
}
.footer {
  height: 50px;
  background-color: #eee;
  border: 1px solid grey;
}
</style>

兄弟组件传参

有两种方式

1. 借助父组件传参

A组件提交一个事件用来传递参数,父组件接受这个事件拿到值,通过props的方式再转给B组件

案例:

父组件

<script setup lang="ts">
// 借助父组件,进行兄弟组件之间的通信
import A from './components/A.vue'
import B from './components/B.vue'
import {ref,Ref} from 'vue'
const title:Ref<string> = ref('hello')
const handleUpdate = (data:string):void => {
  title.value = data
}
</script>

<template>
  <A @update="handleUpdate"></A>
  <B :title="title"></B>
</template>

<style scoped>

</style>

A组件

<script setup lang="ts">
import { ref } from 'vue'
const data = ref('')
// let emit = defineEmits<{
//   (e: 'update', value: string): void
// }>()
const emit = defineEmits(['update'])
</script>

<template>
  <div class="container">
    <div>
      <span>请输入:</span>
      <input type="text" v-model="data">
    </div>
    <button @click="emit('update', data)">提交</button>
  </div>
</template>

<style scoped>

</style>

B组件

<script setup lang="ts">
// 使用defineProps的js和ts写法
defineProps<{
  title: string
}>()
// const props = defineProps({
//   title:{
//     type:String,
//     default:''
//   }
// })
</script>

<template>
  <div class="context">
    <h1>我是b组件</h1>
    <div>
      <span>{{title}}</span>
    </div>
  </div>
</template>

<style scoped>

</style>

2. Event bus

vue3中$on,$off 和 $once 实例方法已被移除,组件实例不再实现事件触发接口,因此大家熟悉的EventBus便无法使用了。然而我们习惯了使用EventBus,对于这种情况我们可以使用Mitt库(其实就是发布订阅模式的设计)

安装:

npm install mitt -S

使用:

再main.ts中

import { createApp } from 'vue'
import App from './App.vue'
import "animate.css"
import Card from "./components/Card.vue";
import mitt from 'mitt';
const emitter = mitt();

declare module "vue" {
    export interface ComponentCustomProperties {
        $Bus: typeof emitter
    }
}

const app = createApp(App)
app.config.globalProperties.$Bus = emitter; // 全局事件总线
app.component("Card",Card).mount('#app')

A组件通过emit派发事件

<script setup lang="ts">
import { ref,getCurrentInstance } from 'vue'
const data = ref('')
const instance = getCurrentInstance()
function handleEmit() {
  instance?.proxy?.$Bus.emit('submit', data.value)
}
</script>

<template>
  <div class="container">
    <div>
      <span>请输入:</span>
      <input type="text" v-model="data">
    </div>
    <button @click="handleEmit">提交</button>
  </div>
</template>

<style scoped>
.container {
  width: 500px;
  height: 500px;
  background-color: #ccc;
  border: 1px solid grey;
  margin: 0 auto;
}
.header {
  height: 50px;
  background-color: #eee;
  border: 1px solid grey;
}
.body {
  height: 400px;
  background-color: #ddd;
  border: 1px solid grey;
}
.footer {
  height: 50px;
  background-color: #eee;
  border: 1px solid grey;
}
</style>

B组件通过on去接受

<script setup lang="ts">
// 使用defineProps的js和ts写法
import {ref,getCurrentInstance} from "vue";
const title = ref('我是b组件的title')
const instance = getCurrentInstance()
// 接受兄弟组件通过mitt传递过来的数据
instance?.proxy?.$Bus.on('submit',(val:string)=>{
  title.value = val
})
</script>

<template>
  <div class="context">
    <h1>我是b组件</h1>
    <div>
      <span>{{title}}</span>
    </div>
  </div>
</template>

<style scoped>
.context {
  width: 500px;
  height: 300px;
  background-color: #ccc;
  border: 1px solid grey;
  margin: 0 auto;
}
 h1 {
  text-align: center;
}
</style>

3使用方法通过emit派发, on 方法添加事件,off 方法移除,clear 清空所有

也可以通过on('*')的方式监控所有组件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值