16 el-tree 保存树的 选择状态, 展开状态

Posted 蓝风9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了16 el-tree 保存树的 选择状态, 展开状态相关的知识,希望对你有一定的参考价值。

前言

需求 来自于一些实际的场景 

这里 仅仅是一个 样例来实现 这一部分需求 

这部分 处理也相对比较简单, 就直接 展示 代码了 

1. 节点 增删改查 的实现(一种基于模型的实现, 一种基于 el-tree api 的实现)

2. 保存 el-tree 的 选择状态 

3. 保存 el-tree 的 展开状态 

样例代码

如下 增删改查两种实现方式, 注释掉的是基于 el-tree 的 api 的使用 

<template>

  <div>
    <div style="width: 20%; float: left;">
      (\\#-_-)\\┯━┯
    </div>

    <div style="width: 20%; float: left;">
      <el-tree
        ref="treeRef"
        :data="tree.nodeList"
        show-checkbox
        node-key="id"
        :default-checked-keys="tree.defaultCheckedKeys"
        :default-expanded-keys="tree.defaultExpandedKeys"
        :check-on-click-node="true"
        :props="tree.defaultProps"
        @node-expand="handleNodeExpand"
        @node-collapse="handleNodeCollapse"
      />
    </div>

    <div style="width: 15%; float: left;">
      <span> 新增 </span>
      <el-select v-model="newNode.parentId" filterable placeholder="请选择父节点">
        <el-option v-for="item in treeNodeList" :key="item.id" :label="item.name" :value="item.id"/>
      </el-select>
      <el-input placeholder="please input id" v-model="newNode.id">
        <template slot="prepend">key</template>
      </el-input>
      <el-input placeholder="please input name" v-model="newNode.name">
        <template slot="prepend">name</template>
      </el-input>
      <el-button @click="handleNewNode">提交</el-button>
    </div>

    <div style="width: 15%; float: left;">
      <span> 更新 </span>
      <el-select v-model="updateNode.id" filterable placeholder="请选择节点">
        <el-option v-for="item in treeNodeList" :key="item.id" :label="item.name" :value="item.id"/>
      </el-select>
      <el-input placeholder="please input name" v-model="updateNode.name">
        <template slot="prepend">name</template>
      </el-input>
      <el-button @click="handleUpdateNode">提交</el-button>
    </div>

    <div style="width: 15%; float: left;">
      <span> 移除 </span>
      <el-select v-model="removeNode.id" filterable placeholder="请选择节点">
        <el-option v-for="item in treeNodeList" :key="item.id" :label="item.name" :value="item.id"/>
      </el-select>
      <el-button @click="handleRemoveNode">提交</el-button>
    </div>

  </div>

</template>

<script>

  export default 
    name: 'ElTreeCrud',
    computed: 
      treeNodeList: function () 
        let collector = []
        this.collectNodeRecursed(this.tree.nodeList, collector)
        return collector
      
    ,
    data () 
      return 
        newNode: 
          parentId: 'backend',
          id: '',
          name: '',
        ,
        updateNode: 
          id: 'backend',
          name: '',
        ,
        removeNode: 
          id: 'backend',
        ,
        tree: 
          nodeList: [
            id: 'backend',
            name: '后端',
            children: [
              
                id: 'backend1',
                name: '后端1',
                children: []
              , 
                id: 'backend2',
                name: '后端2',
                children: []
              
            ]
          , 
            id: 'frontend',
            name: '前端',
            children: [
              
                id: 'frontend1',
                name: '前端1',
                children: []
              , 
                id: 'frontend2',
                name: '前端2',
                children: []
              
            ]
          , 
            id: 'preprocess',
            name: '数据',
            children: [
              
                id: 'preprocess1',
                name: '数据1',
                children: []
              , 
                id: 'preprocess2',
                name: '数据2',
                children: []
              
            ]
          ],
          defaultExpandedKeys: [],
          defaultCheckedKeys: ['backend1', 'preprocess1'],
          defaultProps: 
            children: 'children',
            label: 'name'
          
        
      
    ,
    mounted () 
      window.addEventListener('beforeunload', e => this.beforeLeaveFunc(e))
      this.tree.defaultExpandedKeys = this.treeNodeList.map(ele => ele.id)

      // check if already stored
      // todo, if defaultCheckedKeys is not blank at data's init, then specified node will always be checked
      let treeNodeCheckedKeysStr = sessionStorage.getItem('treeNodeCheckedKeys')
      if (treeNodeCheckedKeysStr) 
        this.tree.defaultCheckedKeys = JSON.parse(treeNodeCheckedKeysStr)
        // JSON.parse(treeNodeCheckedKeysStr).forEach(ele => this.tree.defaultCheckedKeys.push(ele))
      

      let expandedKeysStr = sessionStorage.getItem('expandedKeys')
      if (expandedKeysStr) 
        this.tree.defaultExpandedKeys = JSON.parse(expandedKeysStr)
      
    ,
    created () 

    ,
    methods: 
      // beforeLeaveFunc
      beforeLeaveFunc () 
        let treeRef = this.$refs.treeRef
        let checkedKeys = treeRef.getCheckedKeys()
        sessionStorage.removeItem('treeNodeCheckedKeys')
        sessionStorage.setItem('treeNodeCheckedKeys_tmp', JSON.stringify(checkedKeys))
        if (checkedKeys.length > 0) 
          sessionStorage.setItem('treeNodeCheckedKeys', JSON.stringify(checkedKeys))
        

        // let treePropRoot = treeRef.root
        // let expandedKeys = []
        // this.expandedKeys(treePropRoot, expandedKeys)
        // sessionStorage.removeItem('expandedKeys')
        // sessionStorage.setItem('expandedKeys_tmp', JSON.stringify(expandedKeys))
        // if(expandedKeys.length > 0) 
        //   sessionStorage.setItem('expandedKeys', JSON.stringify(expandedKeys))
        // 
      ,
      // curd
      handleNewNode () 
        if (!this.newNode.id || !this.newNode.name) 
          this.$message.error('please input id and name')
          return
        
        let targetNode = this.lookUpNode(this.tree.nodeList, this.newNode.id)
        if (targetNode) 
          this.$message.error('update node\\'s with id ' + this.newNode.id + ' already exists')
          return
        

        let newNode = 
          id: this.newNode.id,
          name: this.newNode.name,
          children: []
        

        // let treeRef = this.$refs.treeRef
        // treeRef.append(newNode, treeRef.getNode(this.newNode.parentId))
        // this.$message.success(' add new node ' + this.newNode.name + ' at parentNode ' + this.lookUpNode(this.tree.nodeList, this.newNode.parentId).name + ' success')

        let parentNode = this.lookUpNode(this.tree.nodeList, this.newNode.parentId)
        parentNode.children.push(newNode)
      ,
      handleUpdateNode () 
        if (!this.updateNode.id || !this.updateNode.name) 
          this.$message.error('please input id and name')
          return
        
        let targetNode = this.lookUpNode(this.tree.nodeList, this.updateNode.id)
        if (!targetNode) 
          this.$message.error('update node\\'s with id ' + this.newNode.id + ' does not exists')
          return
        

        // let treeRef = this.$refs.treeRef
        // targetNode.name = this.updateNode.name
        // treeRef.updateKeyChildren(this.updateNode.id, targetNode)

        targetNode.name = this.updateNode.name
      ,
      handleRemoveNode () 
        // let treeRef = this.$refs.treeRef
        // let targetNode = this.lookUpNode(this.tree.nodeList, this.removeNode.id)
        // if (!targetNode) 
        //   this.$message.error('update node\\'s with id ' + this.removeNode.id + ' does not exists')
        //   return
        // 
        // treeRef.remove(targetNode)

        let parentNode = this.lookUpParentNode(this.tree.nodeList, null, this.removeNode.parentId)
        let idxOfNode = parentNode.children.map(ele => ele.id).indexOf(this.removeNode.id)
        parentNode.children.splice(idxOfNode, 1)
      ,
      handleNodeExpand (node, nodeProp, treeNode) 
        console.log('handleNodeExpand')
        let treeRef = this.$refs.treeRef
        let treePropRoot = treeRef.root

        let expandedKeys = []
        this.expandedKeys(treePropRoot, expandedKeys)
        sessionStorage.removeItem('expandedKeys')
        sessionStorage.setItem('expandedKeys_tmp', JSON.stringify(expandedKeys))
        if (expandedKeys.length > 0) 
          sessionStorage.setItem('expandedKeys', JSON.stringify(expandedKeys))
        
      ,
      handleNodeCollapse (node, nodeProp, treeNode) 
        // update current node's expand
        nodeProp.expanded = false
        this.handleNodeExpand(node, nodeProp, treeNode)
      ,
      // assist methods
      collectNodeRecursed (nodeList, collector) 
        if (!nodeList) 
          return null
        

        for (let idx in nodeList) 
          let childNode = nodeList[idx]
          collector.push(id: childNode.id, name: childNode.name)

          if (childNode.children) 
            this.collectNodeRecursed(childNode.children, collector)
          
        
      ,
      lookUpNode (nodeList, id) 
        if (!nodeList) 
          return null
        

        for (let idx in nodeList) 
          let childNode = nodeList[idx]
          if (id === childNode.id) 
            return childNode
          

          if (childNode.children) 
            let result = this.lookUpNode(childNode.children, id)
            if (result) 
              return result
            
          
        

        return null
      ,
      lookUpParentNode (nodeList, parentNode, id) 
        if (!nodeList) 
          return null
        

        for (let idx in nodeList) 
          let childNode = nodeList[idx]
          if (id === childNode.id) 
            if (!parentNode) 
              parentNode = 
                children : this.tree.nodeList
              
            
            return parentNode
          

          if (childNode.children) 
            let result = this.lookUpParentNode(childNode.children, childNode, id)
            if (result) 
              return result
            
          
        

        return null
      ,
      expandedKeys (nodeFromRef, collector) 
        if (nodeFromRef.expanded) 
          collector.push(nodeFromRef.data.id)
        
        // 如果不是 root 节点, 并且没有展开, 不继续处理
        if ((nodeFromRef.id !== 0) && (!nodeFromRef.expanded)) 
          return
        

        if (nodeFromRef.childNodes) 
          for (let idx in nodeFromRef.childNodes) 
            let childNode = nodeFromRef.childNodes[idx]
            this.expandedKeys(childNode, collector)
          
        
      
    
  

</script>

<!-- Add 'scoped' attribute to limit CSS to this component only -->
<style scoped>
</style>

选中状态, 展开状态 的持久化和初始化 

刷新页面的时候 保存选中状态 

节点展开/收缩的时候 保存展开状态 

初始化的时候 初始化 选中状态, 展开状态 

展示效果

增删改查的演示 

保存 选中状态, 展开状态 

 

我们看一下 sessionStorage 中存放的 expandedKeys, chekcedKeys 的数据, 是没有问题的

 刷新之后的状态, 可以看到这里 "后端1" 的状态是没有保存下来的, 这是另外的一个问题 

这个我们下一个文章 再来讲解, 需要 调试到 element 的代码 

以上是关于16 el-tree 保存树的 选择状态, 展开状态的主要内容,如果未能解决你的问题,请参考以下文章

17 el-tree defaultCheckedKeys配置 和 树上面选中节点不同步问题

17 el-tree defaultCheckedKeys配置 和 树上面选中节点不同步问题

element-ui el-tree选择子节点时同时选择并提交父节点逻辑问题

el-tree半节点回显

vue el-tree:默认展开第几级节点

vue中使用树控件el-tree如何实现添加加虚线展开树节点样式