項目需求
有個多路搜索框(從服務器搜索),可支持同時根據關鍵字搜索科室和醫生,頁面左側是科室樹,右側是醫生列表表格,當選擇關鍵字搜索結果的某個科室(可獲取到科室id),需要觸發選中左側的科室節點,並查詢出相應的科室所有醫生信息。所以這個不適合直接采用element-ui的節點過濾搜索框來過濾節點,而element-ui也沒有直接根據tree節點值觸發節點點擊的事件,所以需要額外寫代碼來實現這個交互效果。
效果圖



主要實現代碼:
<template>
<el-select
class="searchInput"
v-model="selectedSearchItem"
filterable
remote
reserve-keyword
size="mini"
placeholder="搜索成員或科室"
:remote-method="queryDeptOrDoctor"
@change="selectSearchItem"
:loading="searchLoading">
<el-option-group
v-for="group in searchOptionGroups"
:key="group.name"
:label="group.name">
<el-option
v-for="item in group.options"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-option-group>
</el-select>
<el-tree class="deptTreeCntr"
ref="deptTree"
:data="treeData"
:props="treeProps"
node-key="id"
:default-expanded-keys="['0']"
:expand-on-click-node="false"
@node-click="handleTreeNodeClick">
</el-tree>
</template>
<script>
export default {
data () {
return {
selectedSearchItem: '',
searchLoading: false,
searchOptionGroups: [],
treeData: [],
treeProps: {
value: 'id',
children: 'children',
label: 'title'
},
}
},
methods: {
// 根據關鍵字搜索科室或醫生
queryDeptOrDoctor(keyword){
this.searchOptionGroups = [];
if(keyword == ''){
return;
}
this.searchLoading = true;
// 發起服務器查詢,並組裝this.searchOptionGroups數據
// ...
this.searchLoading = false;
},
// 多路搜索框選擇了搜索的item處理
selectSearchItem(selectedVal){
// selectedVal的前綴用於區分是科室還是醫生,科室是“dept-”開頭,醫生是“doct-”開頭
let type = selectedVal.substring(0, 4);
// 截取實際的科室id或者醫生id
let val = selectedVal.substring(5);
if(type == 'dept') {// 科室
// 設置當前選中key
this.$refs.deptTree.setCurrentKey(val);
// 根據el-tree的getNode方法獲取到val相應的Node
let node = this.$refs.deptTree.getNode(val);
// 觸發點擊處理(由於elem參數沒用到,所以這里忽略不傳)
this.handleTreeNodeClick(node.data, node);
// 除了選中相應的科室節點及觸發查詢,還有件事要做:就是有可能這個節點處於樹比較深的位置,那應該把這個節點的所有父節點都展開(默認不展開)
// 獲取自身及所有父節點的id
let selfAndParentIdArr = this.findTreeParentDataAttr(node, 'id');
if(selfAndParentIdArr.length > 1){
// 這里只展開所有父節點,當前節點不處理
for(let i = 0; i < selfAndParentIdArr.length - 1; i++){
// 這里通過設置節點數據的expanded屬性來展開指定節點
this.$refs.deptTree.store.nodesMap[selfAndParentIdArr[i]].expanded = true;
}
}
}else if(type == 'doct') {// 醫生
// 觸發查詢指定醫生的處理...
}
},
// 點擊樹節點事件處理
handleTreeNodeClick(data, node, elem){
// data.id即為科室id,根據這個科室id觸發醫生表格數據的查詢...
},
// 遞歸找出選擇科室及所有上級科室的data指定屬性(如title、id)
findTreeParentDataAttr(node, attrName, parentNameArr){
if(!parentNameArr){
parentNameArr = [];
}
// 因為是一層一層往上找,這里把父節點放最前面
parentNameArr.unshift(node.data[attrName]);
if(node.data.id == '0'){// 根節點
}else{
this.findTreeParentDataAttr(node.parent, attrName, parentNameArr);
}
// 返回找到的所有節點名稱
return parentNameArr;
}
}
}
</script>
一些屬性、方法說明
el-tree:
data =》 tree的展示數據,類型:array,需要在后端封裝好
props =》 配置選項,類型:object。這個主要用於匹配tree相應節點屬性和后端返回數據的屬性
label:指定節點標簽(即顯示的節點文本)為節點對象的某個屬性值
children:指定子樹為節點對象的某個屬性值
node-key =》 每個樹節點用來作為唯一標識的屬性,整棵樹應該是唯一的
default-expanded-keys =》 默認展開的節點的 key 的數組,由於科室樹都有個默認的根節點id為0,所以這里會默認展開根節點下的一級節點
expand-on-click-node =》 是否在點擊節點的時候展開或者收縮節點, 默認值為 true,如果為 false,則只有點箭頭圖標的時候才會展開或者收縮節點。
node-click =》 節點被點擊時的回調。共三個參數,依次為:傳遞給 data 屬性的數組中該節點所對應的對象、節點對應的 Node、節點組件本身。
setCurrentKey =》 通過 key 設置某個節點的當前選中狀態,使用此方法必須設置 node-key 屬性
getNode =》 根據 data 或者 key 拿到 Tree 組件中的 node
