大数据量树形数据表格展示, umy-ui,

前端树形表格展示通过使用umyui组件

​参考umyui官网的

一个基于 vue 的 PC 端表格UI库,解决万级数据渲染卡顿问题,过万数据点击全选卡顿等等问题。
博主也查阅过资料,也有使用过elementui中的table来实现,但是最后发现因为我的数据有几千条,使用elementui的table会造成浏览器的卡顿,不论是展示数据还是搜索都会使得页面非常卡顿,经过几次试错后,找到了umyui这个在vue基础上的table组件。
umyui链接
👇官网页面如下:我们可以看到基本的分布,这里我使用的是ux-grid这个组件,因为这边需要涉及到复选框,这个属性对有复选框的需求会比较好。推荐有复选框需求的可以使用这个。
在这里插入图片描述
给大家看看最终的效果

👉实现的效果

在这里插入图片描述
搜索这样的树形表格
总的来说,它和elemenyui的table是非常相似的,只需要把elementui的换成就可以了,注意一下里面的属性名称是否一样。
话不多说,来看代码:👇👇👇👇👇👇👇👇👇👇
💞🔥html代码:
要写成树形结构,必须设置row-id=‘id’,这里需要注意,与elementui的table不同,elementui是row-key,
其次,最重要的两个属性是tree-config和checkbox-config

checkbox-config复选框配置项
checkField渲染速度更快(建议数据量大时使用,行数据中必须存在该字段,否则无效)string
showHeader是否显示全选按钮booleantrue
checkAll默认勾选所有(只会在初始化时被触发一次)booleanfalse
checkRowKeys默认勾选开指定行(只会在初始化时被触发一次,需要有 row-id)Array
checkStrictly是否严格的遵循父子不互相关联的做法booleanfalse
checkMethod是否允许勾选的方法,该方法 Function({row}) 的返回值用来决定这一行的 checkbox 是否可以勾选Array
highlight高亮勾选行booleanfalse
trigger触发方式stringdefault(默认), cell(点击单元格触发), row(点击行触发)default
tree-config树形结构配置项
children树子节点的属性stringchildren
indent树节点的缩进number20
expandAll默认展开所有子孙树节点(只会在初始化时被触发一次)booleanfalse
expandRowKeys默认展开指定树节点(只会在初始化时被触发一次,需要有 row-id)string[]
accordion对于同一级的节点,每次只能展开一个booleanfalse
trigger触发方式stringdefault(点击展开按钮触发), cell(点击单元格触发), row(点击行触发)default
lazy是否使用懒加载(启用后只有指定 hasChild 的节点才允许被点击)boolean-false
hasChild只对 lazy 启用后有效,标识是否存在子节点,从而控制是否允许被点stringhasChild
loadMethod该方法 Function({ row }) 用于异步加载子节点, (必须返回 Promise<any[]>对象)Function--
reserve是否保留展开状态,对于某些场景可能会用到,比如数据被刷新之后还保留之前展开的状态(需要有 row-id)boolean-false
showIcon是否显示图标按钮booleantrue
iconOpen自定义展开后显示的图标 iconfont图标string
iconClose自定义收起后显示的图标 iconfont图标string
iconLoaded自定义懒加载中显示的图标 iconfont图标string
line树节点的连接线(启用连接线)booleanfalse
<ux-grid ref="plTreeTable" :data="tableData" fixed-columns-roll beautify-table header-drag-style :max-height="height" :checkbox-config="{highlight: false,showHeader:false,checkRowKeys:checkTreeArry,checkField:'courtTypeHidden'}"
			  @select="handleSelectRow" :tree-config="{ children: 'children',expandAll: false,expandRowKeys:currentExpand}"  row-id="id" border :key="keyCode">
		<ux-table-column  field="name" title="法院名称" :tree-node="true" min-width="15%" type="checkbox">
			<template slot-scope="scope">
				<span>{{scope.row.name}}</span>
			</template>
		</ux-table-column>
		<ux-table-column field="courtType" title="法院类型" align="center" min-width="15%"></ux-table-column>
		<ux-table-column field="courtRelationGood" title="关系很好" align="center" min-width="10%">
			<template slot="header" slot-scope="scope">关系很好
				<el-checkbox label="智能全选" v-model="checkedGood" style="color: #FF8100;display: block" @change="handleCheckedGood"></el-checkbox>
			</template>
			<template slot-scope="scope">
				<el-checkbox label="" v-if="scope.row.courtType"  v-model="scope.row.courtRelationGood" @change="handleCheckedGoodRow(scope.row)"></el-checkbox>
			</template>
		</ux-table-column>
		<ux-table-column field="courtRelationDefalut" title="关系一般" align="center" min-width="10%">
			<template slot="header" slot-scope="scope">关系一般
				<el-checkbox label="智能全选" v-model="checked" style="color: #FF8100;display: block" @change="handleCheckedDefalut"></el-checkbox>
			</template>
			<template slot-scope="scope">
				<el-checkbox label="" v-if="scope.row.courtType" v-model="scope.row.courtRelationDefalut" @change="handleRelationDef(scope.row)"></el-checkbox>
			</template>
		</ux-table-column>
		<ux-table-column field="courtRelationBad" title="关系很差" align="center" min-width="10%">
			<template slot="header" slot-scope="scope">关系很差
				<el-checkbox label="智能全选" v-model="checkedBad" style="color: #FF8100;display: block" @change="handleCheckedBad"></el-checkbox>
			</template>
			<template slot-scope="scope">
				<el-checkbox label="" v-if="scope.row.courtType" v-model="scope.row.courtRelationBad" @change="handleRelationBad(scope.row)"></el-checkbox>
			</template>
		</ux-table-column>
	</ux-grid>

🙌💥需要再第一列添加

:tree-node="true"和type=“checkbox”

在表头我们需要设置一个select选择事件,来记录我们选择了哪几行,以便保存到后台,给后台传递一个state是否选中的状态。
这里我是一层层来写的,大家可以写个递归。

   handleSelectRow(selection, row){
            if(row.children && row.children.length>0){
                    if(row.children && row.children.length>0){
                        row.children.forEach(c=>{
                            if(c.children && c.children.length>0){
                                c.children.forEach(r=>{
                                    if(r.children && r.children.length>0){
                                        r.children.forEach(_l=>{
                                            if(_l.state==0){
                                                _l.state=1
                                            }else {
                                                _l.state=0
                                            }
                                        })
                                    }else{
                                        if(r.state==0){
                                            r.state=1
                                        }else{
                                            r.state=0
                                        }
                                    }
                                })
                            }else{
                                if(c.state==0){
                                    c.state=1
                                }else{
                                    c.state=0
                                }
                            }
                        })
                    }else{
                        if(v.state==0){
                            v.state=1
                        }else{
                            v.state=0
                        }
                    }
                }else{
                row.state=!row.state
            }
            selection.forEach(v=>{
                this.$set(v,'state',true)
            })
            this.checkedAllNode=selection
            this.$refs.plTreeTable.loadData(this.tableData)
            // console.log(selection, row)
        },

对了,如果要设置默认展开和默认选中,可以设置expandRowKeys和checkRowKeys属性。

🙆下面来看搜索树形结构的逻辑(需要控制树形的展开和折叠)

input
👉先介绍一下需要用到的一些属性

size输入框尺寸只在 type!=“textarea” 时有效stringmedium / small / mini
prefix-icon输入框头部图标string
placeholder输入框占位文本string
clearable是否可清空booleanfalse
value-key输入建议对象中用于显示的键名stringvalue
trigger-on-focus是否在输入框 focus 时显示建议列表booleantrue
fetch-suggestions返回输入建议的方法,仅当你的输入建议数据 resolve 时,通过调用 callback(data:[]) 来返回它Function(queryString, callback)
select点击选中建议项时触发选中建议项

👉html代码

<el-autocomplete class="inline-input" v-model.trim="searchForm.queryParam" size="small" value-key="courtName" :fetch-suggestions="querySearchInput" placeholder="请输入法院名称"
:trigger-on-focus="false" @select="handleSelect" suffix-icon="el-icon-search" clearable></el-autocomplete>

👊设置树形展开节点,就必须设置expand-row-keys属性,也必须要设置row-key=“id”,id字段可以自选,但最好可以设置为id

在搜索时,需要展开对应的树形节点,但是有时会出现更新不及时或者说是搜索后表格没有重新渲染,就需要设置 :key=‘’属性
我这里设置了一个:key=“keyCode” 在data中设置了 keyCode:‘keyCode’+new Date().getTime()会实时变化,但对于使用unyui组件的话,也可以使用组件自带的刷新渲染树。
👊刷新表格方法:我使用的是doLayout和loadData,大家根据需求自行设计

doLayout重新计算表格,如果传 true 则进行完整计算(对于某些特殊场景可能会用到,比如隐藏的表格、重新计算列宽…等)
reloadData加载数据并清除所有状态(对于表格数据需要重载、局部递增的场景中可能会用到)data 返回一个Promise
loadData加载数据(对于表格数据需要重载、局部递增场景下可能会用到)data 返回一个Promise
reloadColumn加载列配置并恢复到初始状态(对于表格列需要重载、局部递增场景下可能会用到)columns
loadColumn加载列配置(对于表格列需要重载、局部递增场景下可能会用到)columns
refreshColumn刷新列配置(对于动态修改属性、显示/隐藏列等场景下可能会用到)
reloadRow(rows, record, field)局部加载行数据并恢复到初始状态(对于行数据需要局部更改的场景中可能会用到)rows, record, field
		<el-table :data="tableData"   max-height="700"  size="small" style="width: 100%" ref="table" :key="keyCode"
					  header-cell-class-name="table-header-row"  row-key="id" :tree-props="{children: 'children', hasChildren: 'hasChildren'}" :expand-row-keys="currentExpand.length>0?currentExpand:currentExpandSearchAyyay" >

👉js代码 实现模糊搜索

 /**
         * 获取所有的法院信息--所有的搜索数据
         * @param $table
         */
        querySearch(dataList){
            for(let i=0;i<dataList.length;i++){
                if(dataList[i].courtName){
                    this.allData.push(dataList[i])
                }
                if(dataList[i].children && dataList[i].children.length>0){
                    for(let j=0;j<dataList[i].children.length;j++){
                        if(dataList[i].children[j].courtName){
                            this.allData.push(dataList[i].children[j])
                        }
                        if(dataList[i].children[j].children && dataList[i].children[j].children.length>0){
                             this.querySearch(dataList[i].children[j].children)
                        }
                    }
                }
            }
        },
     /**
         * js搜索模糊查询
         * @param queryString
         * @param cb
         */
        querySearchInput(queryString, cb){
            var restaurants = this.allData;
            var results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants;
            // 调用 callback 返回建议列表的数据
            cb(results);
        },
        createFilter(queryString) {
            return restaurant => {
                return (restaurant.courtName.toLowerCase().indexOf(queryString.toLowerCase())>=0);
            };
        },

搜索树形结构的展开与折叠以及定位到相应的展开节点

这里我有两个搜索内容,一个是类型一个是名称,搜索前先折叠展开的树节点,使用setTreeExpand方法展开相应的节点,接着计算pagingScrollTopLeft需要滚动的距离,这里我的定位还是不准确的,我觉得使用scrollToRow是最好的,但是不知道为什么我的这个方法没有用,对了,这里需要注意一点,这里重新计算表格使用doLayout的方法,loadData会使定位不起作用。

   search() {
            const loading = this.$loading({
                lock: true,
                text: 'Loading',
                spinner: 'el-icon-loading',
                background: 'rgba(0, 0, 0, 0.7)'
            });
            let _this = this
            _this.$refs.plTreeTable.clearTreeExpand()
            _this.$refs.plTreeTable.pagingScrollTopLeft(0,0)
            _this.tableData.forEach(p => {
                if ((_this.searchForm.courtType && _this.searchForm.courtType == p.courtType)
                    && (_this.searchForm.queryParam && _this.searchForm.queryParam == p.name)) {
                    // _this.$refs.plTreeTable.setTreeExpansion(p, true)
                }
                if (p.children && p.children.length > 0) {
                    p.children.forEach(c => {
                        if ((_this.searchForm.courtType && _this.searchForm.courtType == c.courtType)
                            && (_this.searchForm.queryParam && _this.searchForm.queryParam == c.name)) {
                            _this.$refs.plTreeTable.setTreeExpand(p, true)

                        }
                        if((!_this.searchForm.courtType || _this.searchForm.courtType =='')
                            && (_this.searchForm.queryParam && _this.searchForm.queryParam == c.name)){
                            _this.$refs.plTreeTable.setTreeExpand(p, true)

                        }
                        if((_this.searchForm.courtType && _this.searchForm.courtType == c.courtType)
                            && (!_this.searchForm.queryParam || _this.searchForm.queryParam == '')){
                            _this.$refs.plTreeTable.setTreeExpand(p, true)
                            _
                        }
                        if (c.children && c.children.length > 0) {
                            c.children.forEach(r => {
                                if ((_this.searchForm.courtType && _this.searchForm.courtType == r.courtType)
                                    && (_this.searchForm.queryParam && _this.searchForm.queryParam == r.name)) {
                                    _this.$refs.plTreeTable.setTreeExpand(p, true)
                                    _this.$refs.plTreeTable.setTreeExpand(c, true)

                                }
                                if ((!_this.searchForm.courtType || _this.searchForm.courtType == '')
                                    && (_this.searchForm.queryParam && _this.searchForm.queryParam == r.name)) {
                                    _this.$refs.plTreeTable.setTreeExpand(p, true)
                                    _this.$refs.plTreeTable.setTreeExpand(c, true)

                                }
                                if ((_this.searchForm.courtType && _this.searchForm.courtType == r.courtType)
                                    && (!_this.searchForm.queryParam || _this.searchForm.queryParam == '')) {
                                    _this.$refs.plTreeTable.setTreeExpand(p, true)
                                    _this.$refs.plTreeTable.setTreeExpand(c, true)
                                }
                                if (r.children && r.children.length > 0) {
                                    r.children.forEach(_c => {
                                        if ((_this.searchForm.courtType && _this.searchForm.courtType == _c.courtType)
                                            && (_this.searchForm.queryParam && _this.searchForm.queryParam == _c.name)) {
                                            _this.$refs.plTreeTable.setTreeExpand(p, true)
                                            _this.$refs.plTreeTable.setTreeExpand(c, true)
                                            _this.$refs.plTreeTable.setTreeExpand(r, true)
                                        }
                                        if ((!_this.searchForm.courtType || _this.searchForm.courtType == '')
                                            && (_this.searchForm.queryParam && _this.searchForm.queryParam == _c.name)) {
                                            _this.$refs.plTreeTable.setTreeExpand(p, true)
                                            _this.$refs.plTreeTable.setTreeExpand(c, true)
                                            _this.$refs.plTreeTable.setTreeExpand(r, true)
                                        }
                                        if ((_this.searchForm.courtType && _this.searchForm.courtType == _c.courtType)
                                            && (!_this.searchForm.queryParam || _this.searchForm.queryParam == '')) {
                                            _this.$refs.plTreeTable.setTreeExpand(p, true)
                                            _this.$refs.plTreeTable.setTreeExpand(c, true)
                                            _this.$refs.plTreeTable.setTreeExpand(r, true)
                                        }
                                    })
                                }
                            })
                        }
                    })
                }
               loading.close()
            })
            _this.tableData.forEach((v,vi)=>{
                let n=0
                let res=_this.$refs.plTreeTable.isTreeExpandByRow(v)
                let resExpand=_this.$refs.plTreeTable.getTreeExpandRecords()
                resExpand.forEach(c=>{
                    if(c.type=='province'){
                        c.children.forEach((z,x)=>{
                            // if(z.courtType){
                            //     //高级
                            //     n++
                            // }

                            if(z.children && z.children.length>0){
                                    z.children.forEach((r,i)=>{
                                        if(r.courtType){
                                         // 中级
                                            if(r.name==this.searchForm.queryParam){
                                                n+=x
                                                n+=i
                                            }else{
                                                n++
                                            }
                                        }
                                        if(r.children && r.children.length>0){
                                            r.children.forEach((g,y)=>{
                                                if(g.courtType){
                                                    if(g.name==this.searchForm.queryParam){
                                                        n+=i
                                                        n+=x
                                                        n++
                                                        n+=y
                                                        return
                                                    }
                                                }
                                            })
                                        }

                                    })
                                }
                        })
                    }
                })
                console.log(n)
                if(resExpand.length==3){
                    //基层
                    if(res){
                        console.log(vi)
                        // _this.$refs.plTreeTable.scrollToRow(v)
                        _this.$refs.plTreeTable.pagingScrollTopLeft(vi*60+n*30,0)
                    }
                }else if(resExpand.length==1){
                    //高级
                    if(res){
                        console.log(vi,resExpand)
                        // _this.$refs.plTreeTable.scrollToRow(v)
                        _this.$refs.plTreeTable.pagingScrollTopLeft(vi*40+resExpand.length*40,0)
                    }
                }else if(resExpand.length==2){
                    //中级
                    if(res){
                        console.log(vi,resExpand)
                        // _this.$refs.plTreeTable.scrollToRow(v)
                        _this.$refs.plTreeTable.pagingScrollTopLeft(vi*60+n*30,0)
                    }
                }

            })
            // _this.$refs.plTreeTable.loadData(this.tableData)
            _this.$refs.plTreeTable.doLayout(true)
        },

好了,到这就结束了,感觉代码还是写的有点乱的,做完这个功能后感触最深的是需要提前选择对应的组件,这样可以事半功倍。
再见!🙈🙈🙈🙈🙈

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰冰-ying

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值