在开发中,我们构建了组件树之后,除了父子组件之间的通信之外,还会有非父子组件之间的通信。
这里我们主要讲两种方式:
Provide/Inject用于非父子组件之间共享数据:
对于这种情况下,我们可以使用 Provide 和 Inject :
实际上,你可以将依赖注入看作是“long range props”,除了:
我们开发一个这样的结构:
App.vue组件提供数据:
Home.vue是中间的组件:
HomeContent.vue是获取数据的组件:
HomeContent
{{name}}-{{age}}
如果Provide中提供的一些数据是来自data,那么我们可能会想要通过this来获取:
这个时候会报错:
如何解决这个问题呢?
我们先来验证一个结果:如果我们修改了this.names的内容,那么使用length的子组件会不会是响应式的?
我们会发现对应的子组件中是没有反应的:
那么怎么样可以让我们的数据变成响应式的呢?
注意:我们在使用length的时候需要获取其中的value
Vue3从实例中移除了 o n 、 on、 on、off 和 $once 方法,所以我们如果希望继续使用全局事件总线,要通过第三方的库:
首先,我们需要先安装这个库:
npm install mitt
其次,我们可以封装一个工具eventbus.js:
import mitt from 'mitt';
// 可以创建很多个emitter对象
const emitter = mitt();
export default emitter;
在项目中可以使用它们:
Home.vue组件中监听事件:
App.vue中触发事件:
其他API的补充,如果在某些情况下我们想要取消事件,可以使用下面的API:
// 取消emitter中所有的监听
emitter.all.clear()
// 定义一个函数
function onFoo() {}
emitter.on('foo', onFoo) // 监听
emitter.off('foo', onFoo) // 取消监听
在开发中,经常封装一个个可复用的组件:
举个栗子:假如我们定制一个通用的导航组件 - NavBar
这个时候我们就可以来定义插槽slot:
如何使用slot呢?
我们一个组件MySlotCpn.vue:
该组件中有一个插槽,我们可以在插槽中放入需要显示的内容;
MySlotCpn开始
MySlotCpn结尾
我们在App.vue中使用它们:
Hello World
有时候我们希望在使用插槽时,如果没有插入对应的内容,那么我们需要显示一个默认的内容:
我们先测试一个知识点:如果一个组件中含有多个插槽,我们插入多个内容时是什么效果?
事实上,我们希望达到的效果是插槽对应的显示,这个时候我们就可以使用 具名插槽:
在向具名插槽提供内容的时候,我们可以在一个 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:
中间标题
右边i元素
插槽的使用过程如下:
动态插槽名:
具名插槽使用的时候缩写:
中间标题
右边i元素
在Vue中有渲染作用域的概念:
如何理解这句话呢?我们来看一个案例:
但是有时候我们希望插槽可以访问到子组件中的内容是非常重要的:
我们来看下面的一个案例:
具体的代码如下:
App.vue代码:
{{slotProps.item}}-{{slotProps.index}}
ShowNames.vue代码:
如果我们的插槽是默认插槽default,那么在使用的时候 v-slot:default="slotProps"可以简写为v-slot=“slotProps”:
{{slotProps.item}}-{{slotProps.index}}
并且如果我们的插槽只有默认插槽时,组件的标签可以被当做插槽的模板来使用,这样,我们就可以将 v-slot 直接用在组件上:
{{slotProps.item}}-{{slotProps.index}}
但是,如果我们有默认插槽和具名插槽,那么按照完整的template来编写。
只要出现多个插槽,请始终为所有的插槽使用完整的基于 的语法: