1. 顶级类目-面包屑组件的封装
了解render函数和h函数:
render函数的返回值是html结构,渲染到#app容器,相对于template里传入html结构,render函数的优先级更高
h函数是一个创建vnode的函数,它接受三个参数:
-
一个html标签名
-
与这个html标签相关的属性或事件,是一个对象
-
与这个html标签相关的内容或子节点
render函数内部会调用h函数,返回多个vnode组成的虚拟DOM,可以类似看成html结构
需求:
-
创建xtx-bread父容器
-
获取默认插槽内容
-
去除xtx-bread-item组件的i标签,由render函数来生成
-
遍历插槽中的item,得到一个动态创建的节点,最后一个item不加i标签
-
把动态创建的节点渲染到xtx-bread标签中
// xtx-bread组件
<script>
import { h } from 'vue'
export default {
name: 'XtxBread',
// 使用render函数来创建html结构
// render函数内部调用h函数,h函数会生成虚拟Dom节点,组合起来形成虚拟DOM树,也就是vue中的html结构
// h函数接收3个参数:参数1是标签名,参数2是标签的属性(class等),参数3是标签的内容或子节点
// 需求:
// 1.创建一个xtx-bread容器
// 2.获取默认插槽的内容
// 3.去除xtx-bread-item组件的i标签,这个箭头应该由render函数来生成并控制
// 4.遍历插槽中的xtx-bread-item,得到一个动态创建的节点,最后一个item后不加i标签
// 5.把动态创建的节点渲染到xtx-bread容器上
render() {
// 从默认插槽中获取的是一个数组,数组的每一项代表每一个xtx-bread-item组件
const items = this.$slots.default()
const dynamicItems = []
items.forEach((item, i) => {
dynamicItems.push(item)
if (i < items.length - 1) {
dynamicItems.push(h('i', { class: 'iconfont icon-angle-right' }, ''))
}
})
return h('div', { class: 'xtx-bread' }, dynamicItems)
}
}
</script>
<style lang="less">
// 去除scoped属性,使得xtx-bread-item属性可作用于全局
// xtx-bread和xtx-bread-item之间不是父子关系,而是插槽关系,所以使用:deep也是不可以的
// xtx-bread-item 组件
<template>
<!-- 面包屑的单个路由组件item -->
<div class="xtx-bread-item">
<!-- 名字由插槽写入 -->
<router-link v-if="to" :to="to"><slot /></router-link>
<span v-else><slot /></span>
</div>
</template>
<script setup>
defineProps({
to: {
type: [String, Object],
default: ''
}
})
</script>
2. 自动批量注册组件
大致步骤:
-
使用require提供的函数context加载某一个目录下的所有.vue后缀的文件
-
context函数会返回一个导入函数importFn
-
importFn.keys()可以获取所有的文件路径
-
-
拿到文件路径数组,遍历然后使用importFn()根据路径导入组件对象,遍历的同时进行全局注册
const importFn = require.context('./', false, /\.vue$/)
export default {
install(app) {
// 自定义指令
defineDirective(app)
// 自动批量导入组件
importFn.keys().forEach((filePath) => {
// 拿到组件对象
const component = importFn(filePath).default
app.component(component.name, component)
})
}
}
3. 封装二级类目的面包屑
因为二级类目需要处理的逻辑比较复杂,这里额外封装了二级类目的面包屑
二级类目的面包屑html结构
<template>
<!-- 二级类目的面包屑组件封装 -->
<xtx-bread>
<xtx-bread-item to="/">首页</xtx-bread-item>
<transition name="fade-right">
<xtx-bread-item
v-if="category.topCate"
:key="category.topCate.id"
:to="`/category/${category.topCate.id}`"
>
{{ category.topCate.name }}
</xtx-bread-item>
</transition>
<transition name="fade-right">
<xtx-bread-item v-if="category.subCate" :key="category.subCate.id">
{{ category.subCate.name }}
</xtx-bread-item>
</transition>
</xtx-bread>
</template>
逻辑实现:
1. 获取路由的二级类目ID:route.params.id
2.从状态管理中获取存储的一级类目数据,在这里找寻符合id的二级类目,需要配合计算属性查找,因为路由的二级类目ID可以改变,让计算属性依赖于路由的二级类目ID,就可以找到变化的二级类目数据
3.将找到的二级类目和对应的一级类目组合起来,渲染到面包屑组件中
<script setup>
import useCategoryStore from '@/store/category'
import { storeToRefs } from 'pinia'
import { useRoute } from 'vue-router'
import { computed } from 'vue'
const route = useRoute()
const categoryStore = useCategoryStore()
const { list } = storeToRefs(categoryStore)
// 需要的数据对象:category: {topCate: {id: xxx, name: xxx}, subCate: {id: xxx, name: xxx}}
const category = computed(() => {
const cate = {}
list.value.forEach((topCategory) => {
if (topCategory.children) {
// 从每个一级类目的children下找二级类目
const subCategory = topCategory.children.find(
(subCategory) => subCategory.id === route.params.id
)
if (subCategory) {
// 找到二级类目
cate.topCate = { id: topCategory.id, name: topCategory.name }
cate.subCate = { id: subCategory.id, name: subCategory.name }
}
}
})
return cate
})
</script>
标签:01,const,函数,鲜儿,xtx,item,vue3,类目,bread From: https://www.cnblogs.com/jzhFlash/p/16648877.html