关于el-tree组件滚动到指定节点的悲伤故事

1,006 阅读1分钟

先交代一下背景,要求点击右侧table中的行能够打开树中对应数据的父节点并选中当前节点,点击table中的用户管理,左侧树能呈现这种形态。很正常的需求,但是两个nextTick让事情变得有意思了🐕。

image.png 相关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>
  1. 在点击table行时,需要遍历所有树节点,关闭所有节点
  2. 打开当前选中的节点
  3. 如果选中节点不在可视区域,让当前节点滚动到顶部 相关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);
}

在指定节点滚动到顶部有两个注意点:

  1. nodeScroll中要使用异步函数,先切换了选中的节点,再滚动
  2. 千万不可以使用nextTick,千万不可以使用nextTick,千万不可以使用nextTick。如果在nodeScroll中使用nextTickoffsetTop获取的值会是上一选中节点的位置