elment-ui的折叠tree表单实现纯前端搜索,展开收起功能
好久没更新博客了~
记录一下本次做的一个很扯的需求
纯前端去实现这个查询的功能,后台返回的是个数组对象,前端要给他包装成树结构先展示
之后参考代码路径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-table
v-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-table
v-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一直匹配不上…,后来转值了解决