详解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 相关文章推荐
setTimeout和setInterval的浏览器兼容性分析
Feb 27 Javascript
Code: write(s,d) 输出连续字符串
Aug 19 Javascript
Javascript图像处理—亮度对比度应用案例
Jan 03 Javascript
使用JS取得焦点(focus)元素代码
Mar 22 Javascript
javascript表单验证和Window详解
Dec 11 Javascript
jQuery实现行文字链接提示效果的方法
Mar 10 Javascript
JQuery调用绑定click事件的3种写法
Mar 28 Javascript
Javascript实现鼠标右键特色菜单
Aug 04 Javascript
javascript之with的使用(阿里云、淘宝使用代码分析)
Oct 11 Javascript
bootstrap table复杂操作代码
Nov 01 Javascript
angular实现form验证实例代码
Jan 17 Javascript
react native基于FlatList下拉刷新上拉加载实现代码示例
Sep 30 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实现判断访问来路是否为搜索引擎机器人的方法
2015/04/15 PHP
php使用fputcsv实现大数据的导出操作详解
2020/02/27 PHP
jQuery使用zTree插件实现树形菜单和异步加载
2016/02/25 Javascript
AngularJS基础 ng-dblclick 指令用法
2016/08/01 Javascript
JavaScript之面向对象_动力节点Java学院整理
2017/06/29 Javascript
微信小程序 共用变量值的实现
2017/07/12 Javascript
详解利用jsx写vue组件的方法示例
2017/07/17 Javascript
weui框架实现上传、预览和删除图片功能代码
2017/08/24 Javascript
基于Node.js模板引擎教程-jade速学与实战1
2017/09/17 Javascript
微信小程序使用audio组件播放音乐功能示例【附源码下载】
2017/12/08 Javascript
基于JS实现html中placeholder属性提示文字效果示例
2018/04/19 Javascript
基于node搭建服务器,写接口,调接口,跨域的实例
2018/05/13 Javascript
jQuery中each和js中forEach的区别分析
2019/02/27 jQuery
微信小程序在text文本实现多种字体样式
2019/11/08 Javascript
Python中字典的setdefault()方法教程
2017/02/07 Python
Python实现视频下载功能
2017/03/14 Python
使用Pyinstaller的最新踩坑实战记录
2017/11/08 Python
django 按时间范围查询数据库实例代码
2018/02/11 Python
Python实现OpenCV的安装与使用示例
2018/03/30 Python
Python操作Sql Server 2008数据库的方法详解
2018/05/17 Python
基于Django ORM、一对一、一对多、多对多的全面讲解
2019/07/26 Python
Django框架创建项目的方法入门教程
2019/11/04 Python
详解在python操作数据库中游标的使用方法
2019/11/12 Python
python读取dicom图像示例(SimpleITK和dicom包实现)
2020/01/16 Python
如何使用Pytorch搭建模型
2020/10/26 Python
英国护肤品购物网站:Beauty Expert
2016/08/19 全球购物
荷兰在线啤酒店:Beerwulf
2019/08/26 全球购物
门诊挂号室室长岗位职责
2013/11/27 职场文书
广告学毕业生求职信
2014/01/30 职场文书
厨房管理计划书
2014/04/27 职场文书
应届大学生求职信
2014/07/20 职场文书
运动会400米加油稿(8篇)
2014/09/22 职场文书
社区志愿服务活动感想
2015/08/07 职场文书
使用tensorflow 实现反向传播求导
2021/05/26 Python
分析Java中Map的遍历性能问题
2021/06/26 Java/Android
SQL实现LeetCode(177.第N高薪水)
2021/08/04 MySQL