先交代一下背景,要求点击右侧table中的行能够打开树中对应数据的父节点并选中当前节点,点击table中的用户管理,左侧树能呈现这种形态。很正常的需求,但是两个nextTick让事情变得有意思了🐕。
相关html代码如下:
<el-scrollbar class="scrollbar" wrap-class="scrollbar-wrapper" ref="views">
<el-tree class="tree-menu" :filter-node-method="filterNode" ref="menuTree" :data="tree" node-key="no" :props="defaultProps" highlight-current :expand-on-click-node="false" :default-expanded-keys="defaultExpand" @node-expand="expandNode" @node-collapse="collapseNode" @current-change="handleNodeClick">
<div class="custom-tree-node" slot-scope="{ node, data }">
<span class="mgr10 custom--tree-node__label">{{ node.label }}</span>
</div>
</el-tree>
</el-scrollbar>
- 在点击table行时,需要遍历所有树节点,关闭所有节点
- 打开当前选中的节点
- 如果选中节点不在可视区域,让当前节点滚动到顶部 相关js代码如下:
selectMenu (row) {
// 关闭所有节点
let allNode = this.$refs.menuTree.store.nodesMap;
Object.keys(allNode).forEach(el => {
allNode[el].expanded = false;
});
// 选中当前节点
this.getSelectedNode(row);
},
getSelectedNode (row, list = this.tree) {
for (let i = 0; i < list.length; i++) {
let info = list[i];
if (info.children && info.children.length) {
let selectItem = info.children.find(el => el.no === row.no);
if (selectItem) {
this.$nextTick(() => {
this.expandNods = [info.no];
this.defaultExpand = this.expandNods;
this.$refs.menuTree.setCurrentNode(selectItem);
// 节点滚动到顶部
this.nodeScroll();
});
return;
}
this.getSelectedNode(row, info.children);
}
}
},
nodeScroll () {
setTimeout(() => {
// 获取所有节点
let liList = this.$refs.menuTree.$el.getElementsByClassName('is-current');
let offsetTop = liList[0].offsetTop;
let scrollBar = this.$refs.views.$el.querySelector('.scrollbar-wrapper');
if (offsetTop > scrollBar.clientHeight) {
scrollBar.scrollTop = offsetTop;
}
}, 0);
}
在指定节点滚动到顶部有两个注意点:
nodeScroll中要使用异步函数,先切换了选中的节点,再滚动- 千万不可以使用
nextTick,千万不可以使用nextTick,千万不可以使用nextTick。如果在nodeScroll中使用nextTick,offsetTop获取的值会是上一选中节点的位置