_index.js
由于面包屑组件有两部分,因此有一个特殊的_index.js
来处理这个事情,这是为了确保单独导出这个组件的时候还是可以正常使用。如果在打包整个element-ui
时,会单独打包packages
里的两个文件夹breadcrumb
和breadcrumb-item
,这是整套机制比较有趣的地方。
import ElBreadcrumb from './src/breadcrumb';
import ElBreadcrumbItem from './src/breadcrumb-item.vue';
export default function install(Vue) {
Vue.component(ElBreadcrumbItem.name, ElBreadcrumbItem);
Vue.component(ElBreadcrumb.name, ElBreadcrumb);
};
export {
ElBreadcrumb,
ElBreadcrumbItem
};
Breadcrumb
首先是breadcrumb.vue
部分,这是整个面包屑组件的容器。
整体
<template>
<div class="el-breadcrumb">
<slot></slot>
</div>
</template>
可以看出来就是简单的一个div.el-breadcrumb
作为包裹,里面放置一个slot
,这将是breadcrumb-item
。
分隔符
面包屑的分割符是可以定制的。通过传递sepearator
这一prop
即可。
props: {
separator: {
type: String,
default: '/'
}
}
Breadcrumb-item
然后是每一个具体的子项目,写在breadcrumb-item.vue
里面。
整体
<template>
<span class="el-breadcrumb__item">
<span
class="el-breadcrumb__item__inner"
ref="link">
<slot></slot>
</span>
<span
class="el-breadcrumb__separator">
{{separator}}
</span>
</span>
</template>
首先,最外面是一个div.el-breadcrumb__item
包裹,里面是两个span
,一个是具体的内容,一个是分隔符。
inner
里面slot
用于我们自定义连接的具体形式。而ref
是对这个span
进行一个引用,一会儿会用到。
<span
class="el-breadcrumb__item__inner"
ref="link">
<slot></slot>
</span>
separator
另一个span
是分割线的位置,其中的内容是从父级获得的。
<span
class="el-breadcrumb__separator">
{{separator}}
</span>
script
这个组件主要部分的实现在script
里面,因此我们重点分析一下这里。首先是两个prop
,用来配置路由的信息。
props: {
to: {},
replace: Boolean
},
然后,data
里面只有一个separator
,将在mounted
的时候被设置,最主要的逻辑在mounted
,因此我们重点分析一下。
mounted() {
this.separator = this.$parent.separator; // 获取父组件的separator
var self = this; // 保存this对象
if (this.to) { // 如果有to
let link = this.$refs.link; // 获取link的引用
link.addEventListener('click', _ => { // 绑定click事件
let to = this.to;
// 根据replace的值决定是replace还是push,这会影响history的记录
self.replace ? self.$router.replace(to)
: self.$router.push(to);
});
}
}
这部分写代码的人可能有点粗心,先定义了self
来引用this
,然后又混用,其实在这里因为使用了箭头表达式,其实并没有改变this
,无需使用self
来引用this
。此外,对于这种嵌套的组件,其实可以进行一定的检查来确保使用正确。