前言
最近的需求开发中,优惠券管理页面,在原有的header组件中新增了面包屑与导航栏,但其它页面并不需要,考虑到后期的拓展性,便想到了通过vue3中学习到的teleport传送门组件,来解决项目逻辑的耦合问题。
业务要求
正常页面
优惠券管理页面
项目实践
1.简单封装teleport组件
由于项目是基于vue2版本的,所以第一步需要先实现一个vue2版本的传送门组件,以下是一个简单实现。
<template>
<div>
<slot></slot>
</div>
</template>
<script>
export default {
name: 'teleport',
props: {
to: {
type: String,
required: true
}
},
mounted() {
const toEl = document.querySelector(this.to)
if (toEl) {
toEl.appendChild(this.$el)
}
},
destroyed() {
const toEl = document.querySelector(this.to)
if (toEl) {
toEl.removeChild(this.$el)
}
}
}
</script>
实现原理其实很简单,内部通过一个默认插槽,接收外部的ui,在组件挂载成功后,将当前组件元素挂载到目标元素当中,在组件卸载后,从目标元素中移除当前组件元素。
2.改造原来的header组件
只需要在原有的header组件中新增一个占位元素layout-nav,负责接收其它组件传送来的组件元素即可。
header组件部分代码
<div class="main">
<!-- 新增了_layout-nav元素,用于外部扩展 -->
<div id="_layout-nav"></div>
<!---->
<el-dropdown trigger="click" @command="handleCommand">
<span class="el-dropdown-link">
{{userName}}
<i class="el-icon-arrow-down el-icon--right"></i></span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="out">登出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
3.页面使用
如下所示,只需要在管理页面利用teleport组件,将面包屑和导航栏动态插入到目标元素即可,管理页面负责ui的样式及业务逻辑。
<div class="layout">
<!-- 传送门 -->
<teleport to="#_layout-nav">
<div class="header">
<div class="breadcrumb">
<el-breadcrumb separator="/">
<el-breadcrumb-item>首页</el-breadcrumb-item>
<el-breadcrumb-item>小程序管理</el-breadcrumb-item>
<el-breadcrumb-item>领券中心</el-breadcrumb-item>
</el-breadcrumb>
</div>
<ul class="menu">
<li v-for="item in menuList" :key="item.name">
<router-link
active-class="menu-item-active"
:to="{ name: item.name }">{{ item.title }}</router-link>
</li>
</ul>
</div>
</teleport>
<div class="layout-body">
<router-view></router-view>
</div>
</div>