事件总线 和 插槽(slot )的介绍
提示:以下是本篇文章正文内容,下面案例可供参考
可以通过事件总线实现组件之间的通信。
配置全局属性(定义 $bus
为全局属性名,之后可以通过 this.$bus
可以调用 )
app.config.globalProperties.$bus = mitt();
app.config.globalProperties.$inEventName = '输入';
app.mount('#first');
注册事件监听器,要明确 事件事件 和 监听器。
created() {
// 注册事件监听器
// 需要明确 事件名称 和 事件监听器
this.$bus.on( this.$inEventName, this.changeContent );
}
尝试获得指定事件名称对应的监听器数组,成功获取到监听器数组,并且在监听器数组末尾追加新的监听器;如果未能获取到监听器数组,则向 map 中添加新的映射。
on( name, listener ) {
// 先尝试获得指定事件名称对应的监听器数组
let listeners = this.#map.get(name);
// 若成功获取到监听器数组
if( listeners ) {
// 则在监听器数组末尾追加新的监听器
listeners.push(listener);
return;
}
// 若未能获取到监听器数组,则向 map 中添加新的映射
this.#map.set( name, [listener] );
}
尝试获得指定事件名称对应的监听器数组。
emit(name, payload){
// 先尝试获得指定事件名称对应的监听器数组
let listeners = this.#map.get(name);
if( listeners ){
listeners.forEach( fn => fn(payload) );
}
}
off(name) {
if( this.#map.has( name ) ) {
this.#map.delete(name);
}
}
toString() {
return this.#map.entries();
}
mounted() {
console.log( this.$refs );
console.log( this.$refs.unameInput );
}
注意,你只可以在组件挂载后才能访问模板引用。如果你想在模板中的表达式上访问 $refs.input
,在初次渲染时会是 null
。这是因为在初次渲染前这个元素还不存在呢!
把父组件的内容插入到子组件预留好的位置上。
子组件预留的位置为 插槽出口(slot outlet) ,而父组件要插入的内容称为 插槽内容(slot content)。
在子元素中设定标签
作为 插槽出口(slot outlet)。
template: ``,
template: `
点我试试
{{this.text}}
`,
元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。通过使用插槽,
仅负责渲染外层的 (以及相应的样式),而其内部的内容由父组件提供。
在外部没有提供任何内容的情况下,可以为插槽指定默认内容。
template: ``,
template: ``,
如果我们想在父组件没有提供任何插槽内容时在 内渲染“Submit”,只需要将“Submit”写在
标签之间来作为默认内容:
<button type="submit">
<slot>
Submit
slot>
button>
当我们在父组件中使用
且没有提供任何插槽内容时:
<SubmitButton />
“Submit”将会被作为默认内容渲染:
<button type="submit">Submitbutton>
元素可以有一个特殊的 attribute name
,用来给各个插槽分配唯一的 ID,以确定每一处要渲染的内容:
template: `<div class="base-layout">
<header>
<slot name="header">我是头slot>
header>
<main>
<slot>我是中间的slot>
main>
<footer>
<slot name="footer">我是脚slot>
footer>
div>`,
这类带 name
的插槽被称为具名插槽 (named slots)。没有提供 name
的
出口会隐式地命名为“default”。
在父组件中使用
时,我们需要一种方式将多个插槽内容传入到各自目标插槽的出口。此时就需要用到具名插槽了:
要为具名插槽传入内容,我们需要使用一个含 v-slot
指令的 元素,并将目标插槽的名字传给该指令:
<BaseLayout>
<template v-slot:header>
template>
BaseLayout>
v-slot
有对应的简写 #
,因此 可以简写为
。其意思就是“将这部分模板片段传入子组件的 header 插槽中”。
template: `<div class="base-layout">
<header>
<slot name="top" message="顶部">头slot>
header>
<div>
<aside>
<slot name="left" message="中左">中左slot>
aside>
<main>
<slot name="default" message="中右">中右slot>
main>
div>
<footer>
<slot name="bottom" message="底部">脚slot>
footer>
div>`
template: `<BaseLayout>
<template #top="sp">
这里是{{sp.message}}
template>
<template #left="sp">
这里是{{sp.message}}
template>
<template #default="sp">
这里是{{sp.message}}
template>
<template #bottom="sp">
这里是{{sp.message}}
template>
BaseLayout>`