• ELement-UI之树形表格(treeTable&&treeGrid)


    兼容element2.70以下,,,因为官方出了树形表格冲突了。。。。。(不建议使用这个,Vue版的Easyui有树形表格)

    先上图来一波

    支持无限层级,支持新增子级时自动打开父级,支持编辑时自动打开父级,执行操作时自带动画效果,支持初始化时设置全部打开或者关闭,支持一键展开与关闭丝滑般的无延迟

    由于基于el-table扩展的,所以当然能够使用el-table的所有功能

    下面上代码:

    1,核心JS,格式化数据源

    'use strict'
    import Vue from 'vue'
    export default function treeToArray(data, expandAll, parent = null, level = null) {
      let tmp = []
      Array.from(data).forEach(function(record) {
        if (record._expanded === undefined) {
          Vue.set(record, '_expanded', expandAll)
        }
        let _level = 1
        if (level !== undefined && level !== null) {
          _level = level + 1
        }
        Vue.set(record, '_level', _level)
        // 如果有父元素
        if (parent) {
          Vue.set(record, 'parent', parent)
        }
        tmp.push(record)
        if (record.children && record.children.length > 0) {
          const children = treeToArray(record.children, expandAll, record, _level)
          tmp = tmp.concat(children)
        }
      })
      return tmp
    }

    2,扩展el-table

    <template>
      <div>
        <el-table :data="formatData" :row-style="showRow" v-bind="$attrs" @row-click="singleClick"
                  style=" 100%;height: 700px;overflow: hidden" tooltip-effect="dark"
        >
          <el-table-column v-if="columns.length===0" width="150">
            <template slot-scope="scope">
              <span v-for="space in scope.row._level" class="ms-tree-space" :key="space"></span>
              <span class="tree-ctrl" v-if="iconShow(0,scope.row)" @click="toggleExpanded(scope.$index)">
              <i v-if="!scope.row._expanded" class="el-icon-plus"></i>
              <i v-else class="el-icon-minus"></i>
            </span>
              {{scope.$index}}
            </template>
          </el-table-column>
          <el-table-column v-else v-for="(column, index) in columns" :key="column.value" :label="column.text"
                           :width="column.width">
            <template slot-scope="scope">
              <span v-if="index === 0" v-for="space in scope.row._level" class="ms-tree-space" :key="space"></span>
              <span class="tree-ctrl" v-if="iconShow(index,scope.row)" @click="toggleExpanded(scope.$index)">
              <i v-if="!scope.row._expanded" class="el-icon-plus"></i>
              <i v-else class="el-icon-minus"></i>
            </span>
              {{scope.row[column.value]}}
            </template>
          </el-table-column>
          <slot></slot>
        </el-table>
      </div>
    </template>
    
    <script>
    
      import treeToArray from './eval'
    
      export default {
        name: 'treeTable',
        props: {
          data: {
            type: [Array, Object],
            required: true
          },
          columns: {
            type: Array,
            default: () => []
          },
          evalFunc: Function,
          evalArgs: Array,
          expandAll: {
            type: Boolean,
            default: false
          },
          singleClick: Function,
        },
        computed: {
          // 格式化数据源
          formatData: function () {
            let tmp;
            if (!Array.isArray(this.data)) {
              tmp = [this.data]
            } else {
              tmp = this.data
            }
            const func = this.evalFunc || treeToArray;
            const args = this.evalArgs ? Array.concat([tmp, this.expandAll], this.evalArgs) : [tmp, this.expandAll];
            return func.apply(null, args)//赋值function里前两位值data与expandAll
          },
        },
        methods: {
          showRow(row) {
            const show = (row.row.parent ? (row.row.parent._expanded && row.row.parent._show) : true);
            row.row._show = show;
            return show ? 'animation:treeTableShow 1s;-webkit-animation:treeTableShow 1s;' : 'display:none;'
          },
          // 切换下级是否展开
          toggleExpanded(trIndex) {
            const record = this.formatData[trIndex]
            record._expanded = !record._expanded
          },
          // 图标显示
          iconShow(index, record) {
            return (index === 0 && record.children && record.children.length > 0)
          },
    
        }
      }
    </script>
    <style rel="stylesheet/css">
      @keyframes treeTableShow {
        from {
          opacity: 0;
        }
        to {
          opacity: 1;
        }
      }
    
      @-webkit-keyframes treeTableShow {
        from {
          opacity: 0;
        }
        to {
          opacity: 1;
        }
      }
    </style>
    
    <style lang="scss" rel="stylesheet/scss" scoped>
      /*$color-blue:*/
      /*$space- */
      .ms-tree-space {
        position: relative;
        top: 1px;
        display: inline-block;
        font-style: normal;
        font-weight: 400;
        line-height: 1;
         18px;
        height: 14px;
    
      &
      ::before {
        content: ""
      }
    
      }
      .processContainer {
         100%;
        height: 100%;
      }
    
      table td {
        line-height: 26px;
      }
    
      .tree-ctrl {
        position: relative;
        cursor: pointer;
        color: #2196F3;
        margin-left: -18px;
      }
    
      .el-table__body tr.current-row > td {
        background: rgba(185, 221, 249, .75) !important;
      }
    </style>

    3,ReadMe(说明文档)

    ## 写在前面
    此组件仅提供一个创建TreeTable的解决思路
    
    ## prop说明
    #### *data*
      **必填**
    
      原始数据,要求是一个数组或者对象
      ```javascript
        [{
          key1: value1,
          key2: value2,
          children: [{
            key1: value1
          },
          {
            key1: value1
          }]
        },
        {
          key1: value1
        }]
      ```
      或者
     ```javascript
        {
          key1: value1,
          key2: value2,
          children: [{
            key1: value1
          },
          {
            key1: value1
          }]
        }
      ```
    
    #### columns
      列属性,要求是一个数组
    
      1. text: 显示在表头的文字
      2. value: 对应data的key。treeTable将显示相应的value
      3.  每列的宽度,为一个数字(可选)
      
      如果你想要每个字段都有自定义的样式或者嵌套其他组件,columns可不提供,直接像在el-table一样写即可,如果没有自定义内容,提供columns将更加的便捷方便
      
      如果你有几个字段是需要自定义的,几个不需要,那么可以将不需要自定义的字段放入columns,将需要自定义的内容放入到slot中,详情见后文
      ```javascript
      [{
        value:string,
        text:string,
        number
      },{
        value:string,
        text:string,
        number
      }]
      ```
    
    #### expandAll
      是否默认全部展开,boolean值,默认为false
    
    #### evalFunc
      解析函数,function,非必须
    
      如果不提供,将使用默认的[evalFunc](./eval.js)
    
      如果提供了evalFunc,那么会用提供的evalFunc去解析data,并返回treeTable渲染所需要的值。如何编写一个evalFunc,请参考[*eval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/components/TreeTable/eval.js)或[*customEval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/example/table/treeTable/customEval.js)
    
    #### evalArgs
      解析函数的参数,是一个数组
    
      **请注意,自定义的解析函数参数第一个为this.data,第二个参数为, this.expandAll,你不需要在evalArgs填写。一定记住,这两个参数是强制性的,并且位置不可颠倒** *this.data为需要解析的数据,this.expandAll为是否默认展开*
    
      如你的解析函数需要的参数为`(this.data, this.expandAll,1,2,3,4)`,那么你只需要将`[1,2,3,4]`赋值给`evalArgs`就可以了
      
      如果你的解析函数参数只有`(this.data, this.expandAll)`,那么就可以不用填写evalArgs了
      
      具体可参考[*customEval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/example/table/treeTable/customEval.js)的函数参数和[customTreeTable](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/example/table/treeTable/customTreeTable.vue)的`evalArgs`属性值
    
     ## slot
     这是一个自定义列的插槽。
     
     默认情况下,treeTable只有一行行展示数据的功能。但是一般情况下,我们会要给行加上一个操作按钮或者根据当行数据展示不同的样式,这时我们就需要自定义列了。请参考[customTreeTable](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/example/table/treeTable/customTreeTable.vue),[实例效果](http://panjiachen.github.io/vue-element-admin/#/example/table/custom-tree-table)
     
     `slot`和`columns属性`可同时存在,columns里面的数据列会在slot自定义列的左边展示
    
     ## 其他
      如果有其他的需求,请参考[el-table](http://element-cn.eleme.io/#/en-US/component/table)的api自行修改index.vue

    4,使用

     

    一:赋值列(如果需要自定义列,直接在组件里写自定义的列,跟平时写el-table一样)

    二:想要在父组件中使用el-table方法,直接在扩展的el-table加上事件并在props声明:

    三:增加扩展

    1:一键展开与关闭,由于扩展的el-table里是通过属性_expanded控制每级展开或关闭,所以通过递归修改数据源即可实现全部展开与关闭

    2:对其进行增删改时,展开指定行(默认进行操作时全部关闭或者展开)

    思路:还是通过修改数据源,对其父级进行展开即可(可以按需判断执行更细腻的操作),这里的代码就不贴了(需求不一样)

    这里有一个坑,展开的代码放在刷新页面获取新数据的方法里,只不过这里要先通过展开的方法修改请求回来的数据源,然后再赋值页面,,如果相反,页面会发生卡死(有些事件无法点击使用)的意外

     3: 编辑树形table之后el-table选中行保持高亮

    • 子组件中声明方法

    • 父组件中使用(注意子父组件同时添加ref="singleTable"

     findRow(data, row) {//data 编辑之后的数据源  row选中的行
            for (let i = 0; i < data.length; i++) {
              if (data[i].children.length > 0) {
              if (data[i].value === row.value) {//查找编辑之后对应的行新数据
                  this.$refs.singleTable.selectRow(data[i]);//设置高亮行
                  this.row = data[i];//个人需要使用选中的数据
                } else {
                  this.findRow(data[i].children, row);//递归查找
                }
              } else {//没有子级直接比较
                if (data[i].value === row.value) {
                  this.$refs.singleTable.selectRow(data[i]);
                  this.row = data[i];
                }
              }
            }
          }
    • 在刷新页面的代码里使用此方法,注意是新数据源

     

    4:一行直接父级信息获取

    在各方法的有row参数parent属性

    如图:

    原作者:

    https://github.com/PanJiaChen/vue-element-admin/tree/master/src/components/TreeTable
    本人在其进行扩展 提供一种思路,不喜勿喷!!!! 欢迎进群学习交流(927465926)
  • 相关阅读:
    Android中fragment之间和Activity的传值、切换
    IOS后台运行浅析
    IOS7 Background Fetch后台应用程序刷新
    IOS 7四种后台机制
    注册苹果开发者账号的详细步骤
    iOS关闭键盘的两种简单方法
    iOS5 切换中文键盘时覆盖输入框的完美解决方案
    IOS开发之NSLog使用技巧
    IOS总结 静变量static、全局变量extern、局部变量、实例变量
    高德地图初始化 ios
  • 原文地址:https://www.cnblogs.com/wtzl/p/10028677.html
Copyright © 2020-2023  润新知