当只有一层列表的时候:
const list = computed(() => (
keyword.value
? props.data.filter((item: any) => {
return item.title.indexOf(keyword.value) != -1
})
: props.data
))
当有多层列表的时候:
最开始的做法:
const list = computed(() => {
if (keyword.value) {
return search(props.data, keyword.value)
} else {
return props.data
}
})
function search(data: any[], keyword: string): any[] {
let result: any[] = []
for (const item of data) {
if (item.title.includes(keyword)) {
result.push(item)
}
if (item.children && item.children.length > 0) {
const childrenResult = search(item.children, keyword)
result = result.concat(childrenResult)
}
}
return result
}
有问题,没有按层级结构来显示,全放在同一层显示了
接着实现按层级过滤:
const list = computed(() => {
if (keyword.value) {
return search(props.data, keyword.value)
} else {
return props.data
}
})
function search(data: any[], keyword: string): any[] {
return data.filter(node => {
// 判断节点是否匹配关键字
const isMatched = node.title.includes(keyword)
// 递归过滤子节点
if (node.children && node.children.length > 0) {
node.children = search(node.children, keyword)
}
// 如果节点或其子节点匹配关键字,则保留该节点
return isMatched || (node.children && node.children.length > 0)
})
}
发现还是有问题,在第一次筛选之后,将keyword.value的输入关键词删除,会导致列表显示不全的问题,可能是因为在第一次筛选后,search函数修改了原始数据的结构,导致后续的筛选出现问题。
为了解决这个问题,可以在search函数中对节点的子节点进行浅拷贝,以避免修改原始数据的结构。可以使用Object.assign或扩展运算符…来进行浅拷贝。
最后:
const list = computed(() => {
if (keyword.value) {
return search(JSON.parse(JSON.stringify(props.data)), keyword.value)
} else {
return props.data
}
})
function search(data: any[], keyword: string): any[] {
return data.filter(node => {
// 判断节点是否匹配关键字
const isMatched = node.title.includes(keyword)
// 递归过滤子节点
if (node.children && node.children.length > 0) {
node.children = search([...node.children], keyword)
}
// 如果节点或其子节点匹配关键字,则保留该节点
return isMatched || (node.children && node.children.length > 0)
})
}
在这个修改后的代码中,首先使用JSON.parse(JSON.stringify(props.data))进行深拷贝,以获取原始数据的副本。然后在search函数中,对节点的子节点使用扩展运算符[…node.children]进行浅拷贝,以避免修改原始数据的结构。
这样,在每次筛选时都使用原始数据的副本进行操作,不会影响到原始数据的结构,从而解决了列表显示不全的问题。
ok!