vue2树节点刷新后定位到上一节点展开

需求:左侧树针对某一节点进行加锁、解锁处理,处理后的数据需要重新加载树接口,并展开到上一次展开的节点; 可作为有类似场景的代码参考

html 复制代码
  <el-tree
            ref="tree"
            :key="treeKey"
            highlight-current
            lazy
            node-key="node_id"
            :props="props"
            :load="loadNode"
            :default-expanded-keys="showList"
            :expand-on-click-node="false"
            @node-click="clicktree"
            @node-expand="afterNodeExpand"
          >
            <span slot-scope="{ data }" class="custom-tree-node">
              <span
                class="el-tree-node__label"
                :class="{ fnode: data.node_type === 'root' }"
              >
                <em
                  v-if="data.node_type === 'root'"
                  :title="data.name"
                  class="iconEpc icon-cangku mc"
                />
                <em v-else-if="data.node_type === 'dt_CraftRank_01'" class="iconEpc icon-gongsi1 mc" />
                <em v-else-if="data.node_type === 'dt_CraftRank_02'" class="iconEpc icon-chanpinxian mc" />
                <em v-else-if="data.node_type === 'dt_CraftRank_03'" class="iconEpc icon-gongyi mc" />
                <em v-else-if="data.node_type === 'dt_CraftRank_04'" class="iconEpc icon-chejianguanli mc" />
                <em v-else-if="data.node_type === 'dt_CraftRank_05'" class="iconEpc icon-piliangshengchan mc" />
                <em v-else-if="data.node_type === 'dt_CraftRank_06' && data.itemType === 'resource'" class="iconEpc icon-beijing mc" />
                <em v-else-if="data.node_type === 'dt_CraftRank_06'" class="iconEpc icon-server mc" />
                <em v-else-if="data.node_type === 'dt_CraftRank_08'" class="iconEpc icon-beijing mc" />
                &nbsp; &nbsp;&nbsp; &nbsp;{{ getNodeLabel(data) }} &nbsp;
                <span v-if="data.node_type === 'dt_CraftRank_08'" class="tree-btn-group">
                  <em v-if="data.lock == 1" class="el-icon-lock" style="color: #00b4e1;cursor: pointer;width:30px" @click.stop="handleClicklock(data)" /> &nbsp;
                  <em v-else-if="data.lock == 2" class="el-icon-lock" style="color: red;width:30px" @click.stop="handleClickUnlock(data)" />&nbsp;
                </span>
              </span>
            </span>
          </el-tree>
javascript 复制代码
   props: {
        label: 'title',
        isLeaf: 'leaf'
      },
      factoryId: '',
      mfgCenterCode: '',
      showList:[]
    treeKey: 0
javascript 复制代码
methods: {
    // 请求树的接口  写自己的逻辑即可
   loadNode(node, resolve) {
      const craftType = (this.$route.meta && this.$route.meta.craftType) || 'ZZ'
      if (node.level === 0) {
        querytree({ craftType, modelCode: this.selectedModel, jphVersion: this.currentJphVersionType, versionNo: this.currentVersion ? this.currentVersion.versionNo : '' }).then(res => {
          if (res.data.rows.length > 0) {
            this.showList.push(res.data.rows[0].node_id)
            if (res.data.rows[0].isParent === 'true' || res.data.rows[0].isParent === true) {
              res.data.rows[0].leaf = false
            } else {
              res.data.rows[0].leaf = true
            }
            const n = node
            n.data = res.data.rows[0]
            this.rootNode = n
            resolve(res.data.rows)

            this.$nextTick(() => {
              if (this.autoExpandFinished) return
            })
          } else {
            resolve([])
          }
        }).catch(e => {
          console.error('加载树节点失败:', e)
          resolve([])
        })
        return
      }
      if (node.level > 0) {
        querytree({
          'nodeId': node.data.node_id,
          craftType,
          modelCode: this.selectedModel,
          jphVersion: this.currentJphVersionType,
          versionNo: this.currentVersion ? this.currentVersion.versionNo : ''
        }).then(res => {
          if (res.data.rows.length > 0) {
            res.data.rows.forEach(i => {
              if (i.isParent === 'true' || i.isParent === true) {
                this.$set(i, 'leaf', false)
              } else {
                this.$set(i, 'leaf', true)
              }
            })
          }
          return resolve(res.data.rows)
        }).catch(e => {
          console.error('加载树节点失败:', e)
          resolve([])
        })
      }
    },

 
    // 加锁
    handleClicklock(data) {
      this.handleLockToggle(data, 'lock', '加锁')
    },

    // 解锁
    handleClickUnlock(data) {
      this.handleLockToggle(data, 'unlock', '解锁')
    },

    // 加锁/解锁
    handleLockToggle(data, action, actionName) {
      this.$confirm(`确定对此数据${actionName}吗?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        const api = action === 'lock' ? lockZZPrBOP : unlockZZPrBOP
        api({ recordIds: data.id }).then((res) => {
          if (res.data.result == '1') {
            this.$message.success(`${actionName}成功!`)

            // 保存当前路径(用于刷新后定位)
            const savedPath = this.getCurrentPath()

            this._restorePath = [...savedPath]
            this.showList = [...savedPath]

            // 刷新树
            this.$nextTick(() => {
              this.treeKey++
            })

            this.$nextTick(() => {
              setTimeout(() => {
                this.locateToNode(savedPath)
              }, 600)
            })
          }
        })
      }).catch(() => {})
    },

    // 定位到目标节点(带重试)
    locateToNode(path, retries = 5) {
      if (!path || path.length === 0) return
      const tree = this.$refs.tree
      if (!tree) return

      const targetId = path[path.length - 1]
      const targetNode = tree.getNode(targetId)

      if (targetNode && targetNode.data) {
        // 找到了,设置高亮并触发点击
        tree.setCurrentKey(targetId, true)
        this.clicktree(targetNode.data, targetNode, null)
        this._restorePath = null
      } else if (retries > 0) {
        // 节点还未加载,延迟重试
        setTimeout(() => {
          this.locateToNode(path, retries - 1)
        }, 400)
      } else {
        console.log('定位失败,目标节点未加载:', targetId)
      }
    },
    getCurrentPath() {
      const savedPath = []
      let current = this.clicknode
      while (current && current.data && current.data.node_id) {
        // 排除 root 节点
        if (current.data.node_type !== 'root') {
          savedPath.push(current.data.node_id)
        }
        // 遇到 root 直接跳出,避免死循环
        if (current.data.node_type === 'root') {
          break
        }
        current = current.parent
      }
      savedPath.reverse()
      console.log('保存的路径:', savedPath)
      return savedPath
    }

}
相关推荐
biu_biubiu1 小时前
我开源了 Codebook
前端·vue.js
小李科技2 小时前
【性能优化】事件委托:目标定位与 React/Vue 实战
前端·vue.js·react.js·面试·性能优化·前端框架
蓝莓味的口香糖3 小时前
【VUE】【CSS】Vue移动端适配主流方案总结
前端·css·vue.js
切糕师学AI3 小时前
el-select-v2 深度解析:用虚拟滚动解决海量数据下拉选择性能瓶颈
前端·vue.js·elementui·el-select-v2
徐小夕3 小时前
JitOffice:把办公、AI 与审批装进同一个平台
前端·vue.js·github
徐小夕3 小时前
万字分享:为什么我们要自研Word解析引擎?JitWord 解析引擎 4.0 深度复盘
前端·vue.js·github
小大宇4 小时前
Vue知识点-ElementPlus-02图标
前端·javascript·vue.js
king王一帅5 小时前
给你的编辑器加上思维导图、流程图、白板:一套开源组件,多种文档通用
前端·vue.js·ai编程
console.log('npc')1 天前
周期任务功能完整实现:CRON 编辑器 + 模板变量 + 执行历史
javascript·vue.js·编辑器