详解vue-cli+element-ui树形表格(多级表格折腾小计)


Posted in Javascript onApril 17, 2019

前沿

最近在项目开发中需要做一个多级表格,树形表格的功能,看看element-ui上没有,自己开是折腾,话不多说,上思路和代码。

效果图:

详解vue-cli+element-ui树形表格(多级表格折腾小计)

可点击收缩,展开。

一,首先创建一个公共的文件夹treeTable,里边放一个index.vue和eval.js

先看看index.vue,原理就是在element-ui的基础上做了进一步改造。

//利用element-ui的 <template slot-scope="scope">属性,在插入多级表格
<template>
 <el-table :data="formatData" :row-style="showRow" v-bind="$attrs">
  <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>
</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
  }
 },
 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)
  }
 },
 methods: {
  showRow: function(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: function(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: #2196F3;
 $space-width: 18px;
 .ms-tree-space {
  position: relative;
  top: 1px;
  display: inline-block;
  font-style: normal;
  font-weight: 400;
  line-height: 1;
  width: $space-width;
  height: 14px;
  &::before {
   content: ""
  }
 }
 .processContainer{
  width: 100%;
  height: 100%;
 }
 table td {
  line-height: 26px;
 }

 .tree-ctrl{
  position: relative;
  cursor: pointer;
  color: $color-blue;
  margin-left: -$space-width;
 }
</style>

eval.js

/**
 * @Author: hyf
 * @Date:  2018-10-27
 */
'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
}

二,页面中的用法

<template>
 <div class="app-container">
  <tree-table :data="data" :columns="columns" border></tree-table>
 </div>
</template>

<script>
import treeTable from '@/components/TreeTable'
export default {
 name: 'treeTableDemo',
 components: { treeTable },
 data() {
  return {
   columns: [
    {
     text: '事件',
     value: 'event',
     width: 200
    },
    {
     text: 'ID',
     value: 'id'
    },
    {
     text: '时间线',
     value: 'timeLine'
    },
    {
     text: '备注',
     value: 'comment'
    }
   ],
   data: [
    {
     id: 0,
     event: '事件1',
     timeLine: 50,
     comment: '无'
    },
    {
     id: 1,
     event: '事件1',
     timeLine: 100,
     comment: '无',
     children: [
      {
       id: 2,
       event: '事件2',
       timeLine: 10,
       comment: '无'
      },
      {
       id: 3,
       event: '事件3',
       timeLine: 90,
       comment: '无',
       children: [
        {
         id: 4,
         event: '事件4',
         timeLine: 5,
         comment: '无'
        },
        {
         id: 5,
         event: '事件5',
         timeLine: 10,
         comment: '无'
        },
        {
         id: 6,
         event: '事件6',
         timeLine: 75,
         comment: '无',
         children: [
          {
           id: 7,
           event: '事件7',
           timeLine: 50,
           comment: '无',
           children: [
            {
             id: 71,
             event: '事件71',
             timeLine: 25,
             comment: 'xx'
            },
            {
             id: 72,
             event: '事件72',
             timeLine: 5,
             comment: 'xx'
            },
            {
             id: 73,
             event: '事件73',
             timeLine: 20,
             comment: 'xx'
            }
           ]
          },
          {
           id: 8,
           event: '事件8',
           timeLine: 25,
           comment: '无'
          }
         ]
        }
       ]
      }
     ]
    }
   ]
  }
 }
}
</script>

一下为一些整体思路,以及一些说明,方便后续使用

写在前面

此组件仅提供一个创建TreeTable的解决思路

prop说明

data

必填

原始数据,要求是一个数组或者对象

[{
  key1: value1,
  key2: value2,
  children: [{
   key1: value1
  },
  {
   key1: value1
  }]
 },
 {
  key1: value1
 }]

或者

{
   key1: value1,
   key2: value2,
   children: [{
    key1: value1
   },
   {
    key1: value1
   }]
  }

columns

列属性,要求是一个数组

text: 显示在表头的文字
value: 对应data的key。treeTable将显示相应的value
width: 每列的宽度,为一个数字(可选)

如果你想要每个字段都有自定义的样式或者嵌套其他组件,columns可不提供,直接像在el-table一样写即可,如果没有自定义内容,提供columns将更加的便捷方便

如果你有几个字段是需要自定义的,几个不需要,那么可以将不需要自定义的字段放入columns,将需要自定义的内容放入到slot中,详情见后文

[{
 value:string,
 text:string,
 width:number
},{
 value:string,
 text:string,
 width:number
}]

expandAll
是否默认全部展开,boolean值,默认为false

evalFunc
解析函数,function,非必须
如果不提供,将使用默认的evalFunc

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了

slot

这是一个自定义列的插槽。
默认情况下,treeTable只有一行行展示数据的功能。但是一般情况下,我们会要给行加上一个操作按钮或者根据当行数据展示不同的样式,这时我们就需要自定义列了。
slot和columns属性可同时存在,columns里面的数据列会在slot自定义列的左边展示

其他

如果有其他的需求,请参考el-table的api自行修改index.vue

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js实现运动logo图片效果及运动元素对象sportBox使用方法
Dec 25 Javascript
JS onmousemove鼠标移动坐标接龙DIV效果实例
Dec 16 Javascript
JS选中checkbox后获取table内一行TD所有数据的方法
Jul 01 Javascript
JavaScript使用FileSystemObject对象写入文本文件内容的方法
Aug 05 Javascript
在页面中输出当前客户端时间javascript实例代码
Mar 02 Javascript
jQuery通过ajax请求php遍历json数组到table中的代码(推荐)
Jun 12 Javascript
详解Vue中状态管理Vuex
May 11 Javascript
解决vue脚手架项目打包后路由视图不显示的问题
Sep 20 Javascript
vue router 源码概览案例分析
Oct 09 Javascript
如何利用vue+vue-router+elementUI实现简易通讯录
May 13 Javascript
Layui选项卡制作历史浏览记录的方法
Sep 28 Javascript
Node.js API详解之 querystring用法实例分析
Apr 29 Javascript
抖音上用记事本编写爱心小程序教程
Apr 17 #Javascript
基于JS实现web端录音与播放功能
Apr 17 #Javascript
vue-cli的build的文件夹下没有dev-server.js文件配置mock数据的方法
Apr 17 #Javascript
vue component 中引入less文件报错 Module build failed
Apr 17 #Javascript
Vue项目路由刷新的实现代码
Apr 17 #Javascript
vue cli 3.x 项目部署到 github pages的方法
Apr 17 #Javascript
详解vue开发中调用微信jssdk的问题
Apr 16 #Javascript
You might like
使用PHP批量生成随机用户名
2008/07/10 PHP
一周让你学会PHP 不错的学习资料
2009/02/06 PHP
Zend 输出产生XML解析错误
2009/03/03 PHP
PHP读取大文件的类SplFileObject使用介绍
2014/04/09 PHP
本地计算机无法启动Apache故障处理
2014/08/08 PHP
PHP+Ajax实现的博客文章添加类别功能示例
2018/03/29 PHP
thinkPHP5框架设置404、403等http状态页面的方法
2018/06/05 PHP
PHP设计模式之PHP迭代器模式讲解
2019/03/22 PHP
解决Extjs 4 Panel作为Window组件的子组件时出现双重边框问题
2013/01/11 Javascript
js复制到剪切板的实例方法
2013/06/28 Javascript
php跨域调用json的例子
2013/11/13 Javascript
Knockout visible绑定使用方法
2013/11/15 Javascript
js日期对象兼容性的处理方法
2014/01/28 Javascript
JS的参数传递示例介绍
2014/02/08 Javascript
JQuery异步获取返回值中文乱码的解决方法
2015/01/29 Javascript
js实现ctrl+v粘贴上传图片(兼容chrome、firefox、ie11)
2016/03/09 Javascript
JS简单实现tab切换效果的多窗口显示功能
2016/09/07 Javascript
JS实现给json数组动态赋值的方法示例
2020/03/19 Javascript
Vue实现美团app的影院推荐选座功能【推荐】
2018/08/29 Javascript
使用异步组件优化Vue应用程序的性能
2019/04/28 Javascript
详解Java中String JSONObject JSONArray List转换
2020/11/13 Javascript
Vue实现一种简单的无限循环滚动动画的示例
2021/01/10 Vue.js
Python中正则表达式的用法总结
2019/02/22 Python
Python+Opencv实现把图片、视频互转的示例
2020/12/17 Python
django中ImageField的使用详解
2020/12/21 Python
香港永安旅游网:Wing On Travel
2017/04/10 全球购物
Get The Label中文官网:英国运动时尚购物平台
2017/04/19 全球购物
一些.net面试题
2014/10/06 面试题
英语系毕业生自荐信
2013/10/31 职场文书
出国考察邀请函
2014/01/21 职场文书
学生请假条格式
2014/04/11 职场文书
2015年银行客户经理工作总结
2015/04/01 职场文书
2016初一新生军训心得体会
2016/01/11 职场文书
2016学习全国教书育人楷模先进事迹心得体会
2016/01/21 职场文书
大学生暑期社会实践的个人总结!
2019/07/17 职场文书
golang elasticsearch Client的使用详解
2021/05/05 Golang