对这个效果做一个封装
需要准备两个.vue文件,这两个文件都需要在全局注册
1.bread.vue
<script>
// import { h } from 'vue'
export default {
name: 'XtxBread',
render() {
// Vue2中h函数是render的形参
// Vue3的h函数是按需导入的
const slotContent = this.$slots.default().filter(item => item.type.name === 'XtxBreadItem')
const children = []
slotContent.forEach((item, i) => {
console.log(item.type.name)
// 添加单个面包屑组件
children.push(item)
if (i < slotContent.length - 1) {
// 添加一个小箭头(最后一个不添加)
// const iTag = h('i', { class: 'iconfont icon-angle-right' }, null)
// children.push(iTag)
children.push(<i className="iconfont icon-angle-right"></i>)
}
})
// return h('div', { class: 'xtx-bread' }, children)
return <div className="xtx-bread">{children}</div>
}
}
// JSX js的一种扩展(React):就是在js中写HTML标签
// const info = <div>hello</div>
// const msg = 'abc'
// const info = (
// <div>
// <div className='active'>hello</div>
// <div>{msg}</div>
// </div>
// )
// function foo (tag) {
// return (
// <div>
// <div>{tag}</div>
// <div>tom</div>
// </div>
// )
// }
// const tag = foo(<div>hi</div>)
/**
* <div>
<div><div>hi</div></div>
<div>tom</div>
</div>
*/
</script>
<style scoped lang="less">
.xtx-bread {
display: flex;
padding: 25px 10px;
:deep(&-item) {
a {
color: #666;
transition: all 0.4s;
&:hover {
color: @xtxColor;
}
}
}
:deep(i) {
font-size: 12px;
margin-left: 5px;
margin-right: 5px;
line-height: 22px;
}
}
</style>
2.bread-item.vue
<template>
<div class="xtx-bread-item">
<RouterLink v-if="to" :to="to">
<!-- 可以点击跳转 -->
<slot />
</RouterLink>
<span v-else>
<!-- 不可以跳转 -->
<slot />
</span>
<!-- <i class="iconfont icon-angle-right"></i> -->
</div>
</template>
<script>
export default {
name: 'XtxBreadItem',
props: {
to: {
// to的值可以是字符串,也可以是对象
type: [String, Object]
}
}
}
</script>
3.全局注册 基于Vue3
// 扩展vue原有的功能:全局组件,自定义指令,挂载原型方法,注意:没有全局过滤器。
// 这就是插件
// vue2.0插件写法要素:导出一个对象,有install函数,默认传入了Vue构造函数,Vue基础之上扩展
// vue3.0插件写法要素:导出一个对象,有install函数,默认传入了app应用实例,app基础之上扩展
import XtxSkeleton from './skeleton.vue'
import XtxCarousel from './carousel.vue'
import XtxMore from './more.vue'
+ import XtxBread from './bread.vue'
+ import XtxBreadItem from './bread-item.vue'
import defaultImg from '@/assets/images/200.png'
const defineDirective = app => {
// 图片懒加载指令
app.directive('lazyload', {
mounted(el, binding) {
const observer = new IntersectionObserver(
([{ isIntersecting }]) => {
if (isIntersecting) {
observer.unobserve(el)
el.onerror = () => {
el.src = defaultImg
}
el.src = binding.value
}
},
{
threshold: 0.01
}
)
observer.observe(el)
}
})
}
export default {
install(app) {
// 在app上进行扩展,app提供 component directive 函数
// 如果要挂载原型 app.config.globalProperties 方式
app.component(XtxSkeleton.name, XtxSkeleton)
app.component(XtxCarousel.name, XtxCarousel)
app.component(XtxMore.name, XtxMore)
+ app.component(XtxBread.name, XtxBread)
+ app.component(XtxBreadItem.name, XtxBreadItem)
defineDirective(app)
}
}
4.在组件中使用:
<XtxBread>
<XtxBreadItem to="/">首页</XtxBreadItem>
<XtxBreadItem to="/category/1005000">电器</XtxBreadItem>
<XtxBreadItem>空调</XtxBreadItem>
</XtxBread>