####vue tree条件筛选
效果图
组件代码
<div class="my-tree-div">
<div v-if="btnVisible">
<a-button @click="selectAllOrNone(true)">全选</a-button>
<a-button type="dashed" :style="{ marginLeft: '12px' }" @click="selectAllOrNone(false)">全不选</a-button>
</div>
<a-tree v-if="treeData.length" checkable :tree-data="treeData" show-icon :replace-fields="{key:'storeId' }"
:checked-keys="checkKey" @check="onCheck" :selectable="false" :expandedKeys="expandedKeys"
@expand="onExpand" :autoExpandParent="autoExpandParent">
<a-icon slot="icon" type="carry-out"/>
<myIcon slot="rootNode" title="rootNodeIcon"/>
<myIcon slot="company" title="companyIcon"/>
<myIcon slot="open" title="openIcon"/>
<myIcon slot="close" title="closeIcon"/>
<a-icon slot="area" type="environment" />
</a-tree>
</div>
方法代码
export default {
name: 'storeTree',
components: { myIcon },
data () {
return {
treeData: [],
checkKey:[],
selectAll:[],
expandedKeys:[],
backupsExpandedKeys: [],
autoExpandParent: false,
storeStatusList:[]
}
},
mounted () {
this.getStoreInfoList();
},
methods:{
//选中列表
onCheck(checkedKeys) {
this.checkKey = checkedKeys;
},
//展开及收缩
onExpand(expandedKeys) {
this.expandedKeys = expandedKeys
this.autoExpandParent = false
},
//根据父级传入条件筛选树
onSearch(queryParam) {
let params = {};
if(queryParam.cityCode !== undefined){
params.cityCode = queryParam.cityCode[2];
}
if(queryParam.storeName !== undefined){
params.storeName = queryParam.storeName;
}
if (Object.keys(params).length === 0) {
this.expandedKeys = []
} else {
this.expandedKeys = []
this.backupsExpandedKeys = []
const candidateKeysList = this.getKeyList(
params,
this.treeData,
[]
)
this.selectAll = candidateKeysList;
candidateKeysList.forEach((item) => {
const key = this.getParentKey(item, this.treeData)
if (key && !this.backupsExpandedKeys.some((item) => item === key)){
this.backupsExpandedKeys.push(key)
}
})
const { length } = this.backupsExpandedKeys
for (let i = 0; i < length; i++) {
this.getAllParentKey(
this.backupsExpandedKeys[i],
this.treeData
)
}
this.expandedKeys = this.backupsExpandedKeys.slice()
this.autoExpandParent = true;
}
},
// 获取节点中含有value的所有key集合
getKeyList(params, tree, keyList) {
for (let i = 0; i < tree.length; i++) {
const node = tree[i]
let flag = false;
if(Object.keys(params).length > 1){
if (node.cityCode.indexOf(params.cityCode) > -1 && node.storeName.indexOf(params.storeName) > -1) {
flag = true;
keyList.push(node.storeId)
}
}else if(params.cityCode !== undefined && node.cityCode === params.cityCode){
flag = true;
keyList.push(node.storeId)
}else if(params.storeName !== undefined && node.storeName.indexOf(params.storeName) > -1){
flag = true;
keyList.push(node.storeId)
}
if (node.children) {
this.getKeyList(params, node.children, keyList)
}
if(flag){
delete node['style']
}else{
node['style'] = 'display: none'
}
}
return keyList
},
// 该递归主要用于获取key的父亲节点的key值
getParentKey(key, tree) {
let parentKey
let temp
for (let i = 0; i < tree.length; i++) {
const node = tree[i]
if (node.children) {
if (node.children.some((item) => item.storeId === key)) {
parentKey = node.storeId
delete node['style']
} else if ((temp = this.getParentKey(key, node.children))) {
parentKey = temp
}
}
}
return parentKey
},
// 获取该节点的所有祖先节点
getAllParentKey(key, tree) {
let parentKey
if (key) {
parentKey = this.getParentKey(key, tree)
if (parentKey) {
if (!this.backupsExpandedKeys.some((item) => item === parentKey)) {
this.backupsExpandedKeys.push(parentKey)
}
let temp = tree.filter(t => t.storeId === parentKey);
if(temp.length > 0){
delete temp[0]['style']
}
this.getAllParentKey(parentKey, tree)
}
}
},
//获取初始化数据
initTree (supplierId) {
this.$request({
url: '/storeInfo/resultAl******',
method: 'get',
}).then(res => {
let data = res.data;
this.treeData = this.setIcon(data.list);
this.selectAll = data.selectAll;
if(supplierId !== '' && supplierId !== undefined){
this.getSupplierStore(supplierId);
}
})
},
//全选或反选
selectAllOrNone(flag){
let temp = [...new Set([...this.checkKey, ...this.selectAll])]
this.checkKey = flag ? temp : [];
},
//根据条件生成带icon的树状data
setIcon (data) {
data.map(item => {
item.title = item.nodeType !== '2' ? item.storeName : item.storeName + '(' + this.storeStatusList.find(t => t.code === item.storeStatus).name + ')';
if (item.nodeType !== '0') {
//子公司
if(item.nodeType === '1'){
item.slots = { icon: 'company' }
}else if(item.nodeType === '3'){
item.slots = { icon: 'area' }
}else{
item.slots = { icon: 'open' }
}
} else {
item.slots = { icon: 'rootNode' }
}
if (item.children) {
this.setIcon(item.children)
}
})
return data
},
getStoreInfoList(){
this.$request({
url: '/common/getStore********',
method: 'get',
}).then(res => {
this.storeStatusList = res.data;
})
}
}
}
核心代码
if(flag){
delete node['style']
}else{
node['style'] = 'display: none'
}
思路一 保留已选中但非筛选条件的值
1、先递归循环所有的节点并让其都隐藏
2、遇到符合条件的去掉隐藏属性,把当前节点及所有上级节点都展示
开始也想过直接remove不符合的节点,但这样就会导致已选中但非筛选条件的值丢失,所以只能隐藏
思路二 只保存符合筛选条件的值
1、直接递归循环,判断最底层的children为空时通过filter(t => t.code === code)筛选符合条件的数组
2、判断数组的children是否为空,为空则直接跳过,不为空追加到新的数组再赋值给treeData