項目需求
有個多路搜索框(從服務器搜索),可支持同時根據關鍵字搜索科室和醫生,頁面左側是科室樹,右側是醫生列表表格,當選擇關鍵字搜索結果的某個科室(可獲取到科室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