在封装面包屑组件发现,简单封装的面包屑组件的时候如果最后一个选项后不需要箭头,还需要单独进行样式更改,并且如果需要在中间的某一个选项需要进行特殊样式,则更加复杂,这种只适用于两级场景,多级场景下就不能使用。
因此选择封装一个高复用的面包屑组件,能适用于多级场景,用到了 render 选项和 h 函数。
参考element的面包屑组件,不需要对不同要求再进行专门设计,这正是我需要的。
通过bread和bread-item两个组件进行演示:(以下基于vue3.0,所有组件都定义为全局组件)
1.bread-item.vue
<template>
<div class="bread-item">
<RouterLink v-if="to" :to="to"><slot /></RouterLink>
<span v-else><slot /></span>
</div>
</template>
<script>
export default {
name: 'BreadItem',
props: {
to: {
type: [String, Object],
default: ''
}
}
}
</script>
<style></style>
此处并不需要加入箭头,如果在此处加上则最后会多出一个不需要的箭头,将箭头在render中动态渲染就好了
2.bread.vue
<script>
import { h } from 'vue'
export default {
name: 'Bread',
render() {
const items = this.$slots.default()
const dymanicItems = []
items.forEach((item, i) => {
dymanicItems.push(item)
if (i < items.length - 1) {
dymanicItems.push(h('i', { class: 'arrow' }))
}
})
return h('div', { class: 'bread' }, dymanicItems)
}
}
</script>
<style lang="less">
.bread {
display: flex;
padding: 25px 10px;
&-item {
a {
color: #666;
transition: all 0.4s;
&:hover {
color: @xtxColor;
}
}
}
i {
font-size: 12px;
margin-left: 5px;
margin-right: 5px;
line-height: 22px;
}
}
</style>
此处样式没有scoped,是为了里面的bread-item插槽也能使用
index.vue
<template>
<div class="top-category">
<div class="container">
<!-- 面包屑 -->
<Bread>
<BreadItem :to="{ path: '/' }">首页</BreadItem>
<BreadItem to="/category">页面1</BreadItem>
<BreadItem>页面2</BreadItem>
</Bread>
</div>
</div>
</template>
<script>
export default {
name: 'TopCategory'
}
</script>
<style></style>
最后在使用的时候就和element上的面包屑组件一样,需要跳转就加一个to
分析一下bread.vue中的代码
<script>
import { h } from 'vue'
export default {
name: 'Bread',
render() {
const items = this.$slots.default()
const dymanicItems = []
items.forEach((item, i) => {
dymanicItems.push(item)
if (i < items.length - 1) {
dymanicItems.push(h('i', { class: 'arrow' }))
}
})
return h('div', { class: 'bread' }, dymanicItems)
}
}
</script>
这里用到了creatElement函数和render选项
在Vue中指定组件显示的内容:new Vue({选项}),有三种方式
- el 选项,通过一个选择器找到容器,容器内容就是组件内容
- template 选项,
<div>组件内容</div>
作为组件内容 - render选项,它是一个函数,函数回默认传入createElement函数(h函数),这个函数用来创建结构,再render函数返回渲染为组件内容。它的优先级更高。
vue官方对render选项的解释是:字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。该渲染函数接收一个 createElement
方法作为第一个参数用来创建 VNode
。Vue 选项中的 render
函数若存在,则 Vue 构造函数不会从 template
选项或通过 el
选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。
render函数的返回值就是html结构
在大多数情况下,我们可以使用模板创建HTML,但一些特殊情况下使用模板较为繁琐,可以使用渲染函数来解决
h函数有三个参数 1.节点名称 2.属性|数据 (对象) 3. 子节点,例如:h('div', { class: 'bread' }, "例子"),生成的就是 <div class="bread">例子</div>
在上述代码中,items是通过this.$slots.default()获取的所有插槽组成的数组,dymanicItems就是动态渲染的箭头图标
通过遍历items得到每一个插槽将其与箭头图标依次组合,并通过if判断去掉最后一个箭头,就完成了 首页>页面1>页面2 这样的结构
更多内容和例子可以参考vue官方文档