好久没更新博客了~
记录一下本次做的一个很扯的需求
纯前端去实现这个查询的功能,后台返回的是个数组对象,前端要给他包装成树结构先展示
之后参考代码路径src\views\goods\category\index.vue
需求描述:
搜索输入任何一个关键字,都会展开他的父级,两个栏目都包含了,那么两个父级都展开
先模拟数据,上代码:
categoryList=[{categoryName:'测试1',children:[{categoryName:'haha1',children:[]},]},{categoryName:'测试2',children:[{categoryName:'haha2',children:[]},]},{categoryName:'钦佩',children:[{categoryName:'haha2',children:[]},]}
]
<el-tablev-loading="loading":data="categoryList"row-key="categoryId"stripe:tree-props="{ children: 'children', hasChildren: 'hasChildren' }":expand-row-keys="expandedCategoryIds"><el-table-column label="分类名称" prop="categoryName" /><el-table-column label="分类等级" prop="level" /><el-table-column label="状态" prop="status" :formatter="statusFormat" /><el-table-column label="关键字" prop="keywords" /><el-table-column label="排序" prop="sortNum" /><el-table-column label="创建时间" prop="createTime" width="180" /><el-table-column label="操作" min-width="120"></el-table-column></el-table>
根据categoryName进行前端模糊搜索,会递归categoryList 里面所有的值,包括children,children的不固定多少级,
比如我所有一个haha,不管是哪一级,都会把,包含这个haha的都展开,别的项目也不会隐藏
<el-input
v-model=“searchText”
placeholder=“请输入搜索关键词”
class=“inpClass”
clearable
@keydown.enter.native=“onSearchChange”
data() {return {searchText: "",}}
// 处理搜索onSearchChange() {const expandIds = new Set();// 递归搜索函数const searchInCategory = (categories, parentIds = []) => {if (!categories) return false;let hasMatch = false;for (const category of categories) {const currentIds = [...parentIds, category.categoryId];// 检查当前项是否匹配const isMatch = category.categoryName.toLowerCase().includes(this.searchText.toLowerCase());// 递归检查子项const hasChildMatch = searchInCategory(category.children, currentIds);// 如果当前项或子项匹配,添加所有父级ID到展开集合if (isMatch || hasChildMatch) {currentIds.forEach((id) => expandIds.add(id));hasMatch = true;}}return hasMatch;};if (this.searchText) {searchInCategory(this.categoryList);this.expandedCategoryIds = Array.from(expandIds).map(String);} else {// 确保设置一个新的空数组this.expandedCategoryIds = [];// 2. 确保在DOM更新后执行收起操作this.$nextTick(() => {// 3. 遍历所有数据强制收起const closeRows = (data) => {data.forEach((row) => {if (this.$refs.tableRef) {this.$refs.tableRef.toggleRowExpansion(row, false);}if (row.children && row.children.length) {closeRows(row.children);}});};closeRows(this.categoryList);});}},
在获取列表数据的时候也进行初始化数据
/** 查询商品分类列表 */getList() {this.loading = true;listCategory(this.queryParams).then((response) => {if (response.data) {this.categoryList = this.handleTree(response.data, "categoryId");this.expandedCategoryIds = [];// 2. 确保在DOM更新后执行收起操作this.$nextTick(() => {// 3. 遍历所有数据强制收起const closeRows = (data) => {data.forEach((row) => {if (this.$refs.tableRef) {this.$refs.tableRef.toggleRowExpansion(row, false);}if (row.children && row.children.length) {closeRows(row.children);}});};closeRows(this.categoryList);});}this.loading = false;});},
这样就实现纯前端去模拟搜索的效果
注意,后来又遇到一个问题:
<el-tablev-loading="loading":data="categoryList"row-key="categoryId"stripe:tree-props="{ children: 'children', hasChildren: 'hasChildren' }":expand-row-keys="expandedCategoryIds">categoryList 的树形结构里面有categoryId,我直接设置下面这个,也不会展开expandedCategoryIds: [758, 753, 748]
因为element-ui会把那个数值自动转换为String一直匹配不上…,后来转值了解决