事件总线 和 插槽(slot )

事件总线 和 插槽(slot )的介绍


提示:以下是本篇文章正文内容,下面案例可供参考

一、事件总线

可以通过事件总线实现组件之间的通信。

配置全局属性(定义 $bus 为全局属性名,之后可以通过 this.$bus 可以调用 )

 app.config.globalProperties.$bus = mitt();
 app.config.globalProperties.$inEventName = '输入';
 app.mount('#first');

注册事件监听器,要明确 事件事件 和 监听器。

created() {
    // 注册事件监听器
    // 需要明确 事件名称 和 事件监听器
    this.$bus.on( this.$inEventName, this.changeContent );
}

1. 手动实现事件监听和触发

尝试获得指定事件名称对应的监听器数组,成功获取到监听器数组,并且在监听器数组末尾追加新的监听器;如果未能获取到监听器数组,则向 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();
    }

2.模板引用

在这里插入图片描述
挂载结束后引用都会被暴露在 this.$refs 之上:

 mounted() {
     console.log( this.$refs );
     console.log( this.$refs.unameInput );
 }

注意,你只可以在组件挂载后才能访问模板引用。如果你想在模板中的表达式上访问 $refs.input,在初次渲染时会是 null。这是因为在初次渲染前这个元素还不存在呢!

二、插槽(slot )

把父组件的内容插入到子组件预留好的位置上。

1.插槽出口(slot outlet)和插槽内容(slot content)

子组件预留的位置为 插槽出口(slot outlet) ,而父组件要插入的内容称为 插槽内容(slot content)。

在子元素中设定标签 <slot> 作为 插槽出口(slot outlet)

  template: `<button @click="handleClick">
                <slot></slot>
             </button>`,

在这里插入图片描述
而在父元素中在标签 <FancyButton>

  template: `<div class="wrapper">
                <FancyButton>点我试试</FancyButton>
                <FancyButton>{{this.text}}</FancyButton>
             </div>`,

<slot> 元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。通过使用插槽,<FancyButton> 仅负责渲染外层的 <button> (以及相应的样式),而其内部的内容由父组件提供。

默认内容

在外部没有提供任何内容的情况下,可以为插槽指定默认内容。

 template: `<button @click="handleClick">
               <slot>
                 默认内容
               </slot>
            </button>`,
 template: `<button @click="handleClick">
               <slot>
                 默认内容
               </slot>
            </button>`,

如果我们想在父组件没有提供任何插槽内容时在 <button> 内渲染“Submit”,只需要将“Submit”写在 <slot> 标签之间来作为默认内容:

<button type="submit">
  <slot>
    Submit <!-- 默认内容 -->
  </slot>
</button>

当我们在父组件中使用 <SubmitButton> 且没有提供任何插槽内容时:

<SubmitButton />

“Submit”将会被作为默认内容渲染:

<button type="submit">Submit</button>

2.具名插槽

<slot> 元素可以有一个特殊的 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<slot> 出口会隐式地命名为“default”。

在父组件中使用 <BaseLayout> 时,我们需要一种方式将多个插槽内容传入到各自目标插槽的出口。此时就需要用到具名插槽了:

要为具名插槽传入内容,我们需要使用一个含 v-slot 指令的 <template> 元素,并将目标插槽的名字传给该指令:

<BaseLayout>
  <template v-slot:header>
    <!-- header 插槽的内容放这里 -->
  </template>
</BaseLayout>

v-slot 有对应的简写 #,因此 <template v-slot:header> 可以简写为 <template #header>。其意思就是“将这部分模板片段传入子组件的 header 插槽中”。
在这里插入图片描述

3.作用域插槽

在这里插入图片描述

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>`

在这里插入图片描述


  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值