[转]iView Cascader、Tree 数据处理

原文地址:https://www.jianshu.com/p/1daf7d762502

iView 有个 Cascader、Tree 组件,数据要求比较严格(简直弱爆了好吗...)

问题简述

Cascader 数据要求一览(Tree 其实类似):
{
    value: ‘jiangsu‘,
    label: ‘江苏‘,
    children: [
        {
            value: ‘nanjing‘,
            label: ‘南京‘,
            children: [
                {
                    value: ‘fuzimiao‘,
                    label: ‘夫子庙‘,
                }
            ]
        }, {
            value: ‘suzhou‘,
            label: ‘苏州‘,
            children: [
                {
                    value: ‘zhuozhengyuan‘,
                    label: ‘拙政园‘,
                }, {
                    value: ‘shizilin‘,
                    label: ‘狮子林‘,
                }
            ]
        }
    ]
}

即:

value
    label
    children [可选]

发个牢骚

呃,谁的数据结构默认会是这样的?肯定很少,几乎没有....不服咬我

话说就不能通过传递 value、label、children 的键值映射就配置 OK 了吗,非得每个使用的地方转一遍数据,累...就没爱过
数据递归处理

好吧,做完一个项目了,稍微整理整理...

总得来说,这种数据还是比较好处理的。既然是树结构,其实和 Cascader 组件所要求的数据格式基本类似,无非字段名称不一样,字段可能更多而已。

比如项目中某个需要展示部分数据:
[
    {
        "department_id": 1,
        "department_name": "Test",
        "super_department_id": "0",
        "child_departments": [
            {
                "department_id": "34",
                "department_name": "修图",
                "super_department_id": "1",
                "child_departments": []
            },
            {
                "department_id": "35",
                "department_name": "系统研发",
                "super_department_id": "1",
                "child_departments": [
                    {
                        "department_id": "48",
                        "department_name": "测试组",
                        "super_department_id": "35",
                        "child_departments": []
                    },
                    {
                        "department_id": "49",
                        "department_name": "产品组",
                        "super_department_id": "35",
                        "child_departments": []
                    },
                    {
                        "department_id": "50",
                        "department_name": "运营",
                        "super_department_id": "35",
                        "child_departments": []
                    },
                    {
                        "department_id": "51",
                        "department_name": "技术开发组",
                        "super_department_id": "35",
                        "child_departments": []
                    }
                ]
            }
        ]
    }
]

那么需要做的转换如下:

department_id -> value
    department_name -> label
    children -> child_departments

这个做个简单的递归就解决了,代码、注释如下:
/**
 * tree 数据转换
 * @param  {Array} tree 待转换的 tree
 * @return {Array}      转换后的 tree
 */
function convertTree (tree) {
    const result = []

// 遍历 tree
    tree.forEach((item) => {
        // 解构赋值
        let {
            department_id: value,
            department_name: label,
            child_departments: children
        } = item

// 如果有子节点,递归
        if (children) {
            children = convertTree(children)
        }

result.push({
            value,
            label,
            children
        })
    })

return result
}

最终得到数据如下:
[
    {
        "value": 1,
        "label": "Test",
        "children": [
            {
                "value": "34",
                "label": "修图",
                "children": []
            },
            {
                "value": "35",
                "label": "系统研发",
                "children": [
                    {
                        "value": "48",
                        "label": "测试组",
                        "children": []
                    },
                    {
                        "value": "49",
                        "label": "产品组",
                        "children": []
                    },
                    {
                        "value": "50",
                        "label": "运营",
                        "children": []
                    },
                    {
                        "value": "51",
                        "label": "技术开发组",
                        "children": []
                    }
                ]
            }
        ]
    }
]

在线演示地址:https://jsfiddle.net/Roam/5xxcjfk8/

貌似结束了

其实好像也就那么回事,十来行代码就敲定了。
但是,回头一想,也不对,每种数据都要写个转换,也是神烦 = =
好吧,继续优化优化吧...

其实可以把递归函数再改改:
/**
 * tree 数据转换
 * @param  {Array} tree 待转换的 tree
 * @param  {Object} map  键值对映射
 * @return {Array}      转换后的 tree
 */
function convertTree (tree, map) {
    const result = []

// 遍历 tree
    tree.forEach((item) => {
        // 读取 map 的键值映射
        const value = item[ map.value ]
        const label = item[ map.label ]
        let children = item[ map.children ]

// 如果有子节点,递归
        if (children) {
            children = convertTree(children, map)
        }

result.push({
            value,
            label,
            children
        })
    })

return result
}

就是增加了一个 map 参数,用于指定 value、label、children 的字段映射:
{
    value: ‘department_id‘,
    label: ‘department_name‘,
    children: ‘child_departments‘
}

这样这个递归方法就可以抽出来了,需要转换的地方,调这个方法就行了
感觉可以提个 feature
再来个复杂点的数据处理

在做部门展示权限的时候,遇到个问题,简化如下:

如果一个节点有权限,那么显示该节点,且显示所属的父节点
    如果该节点有权限,且该节点有子节点,子节点全部显示

用图描述一下好了:
selected-tree.png

A 为 root 节点
    绿色表示有权限

需要将上面的转换得到如下 tree 结构:
filtered-tree.png

用数据来说话就是:
 [
    {
        "name": "A",
        "children": [
            {
                "name": "B",
            }, {
                "name": "C",
                "children": [
                    {
                        "name": "E",
                        "visible": true
                    }, {
                        "name": "F"
                    }
                ]
            }, {
                "name": "D",
                "visible": true,
                "children": [
                    {
                        "name": "G"
                    }, {
                        "name": "H"
                    }, {
                        "name": "I"
                    }
                ]
            }
        ]
    }
]

转成:
[
    {
        "name": "A",
        "children": [
            {
                "name": "C",
                "children": [
                    {
                        "name": "E",
                        "visible": true
                    }
                ]
            }, {
                "name": "D",
                "visible": true,
                "children": [
                    {
                        "name": "G"
                    }, {
                        "name": "H"
                    }, {
                        "name": "I"
                    }
                ]
            }
        ]
    }
]

初看一脸懵逼
再看还是一脸懵逼....

细细捋一捋...

遍历树
    如果当前节点有权限,塞进来
    如果当前节点无权限,并且无子节点,抛弃
    如果当前节点无权限,遍历子节点(重复如上)

嗯~ o( ̄▽ ̄)o,就是这样的...

这里有个技巧,就是使用 Array.prototype.filter()
 // 原始数据
 const raw = [
    {
        "name": "A",
        "children": [
            {
                "name": "B",
            }, {
                "name": "C",
                "children": [
                    {
                        "name": "E",
                        "visible": true
                    }, {
                        "name": "F"
                    }
                ]
            }, {
                "name": "D",
                "visible": true,
                "children": [
                    {
                        "name": "G"
                    }, {
                        "name": "H"
                    }, {
                        "name": "I"
                    }
                ]
            }
        ]
    }
]

/**
 * Tree 过滤
 * @param  {Array} tree 待过滤的 tree
 * @return {Array}      已过滤的 tree
 */
function filterTree (tree) {
    let result = []

// filter 遍历
    result = tree.filter((item) => {
        // 如果有权限
        if (item.visible) {
            return true

// 如果有子节点,递归子节点
        // 如果有权限,返回的值应该为非空数组
        } else if (item.children && item.children.length > 0) {
            item.children = filterTree(item.children)

return item.children.length > 0

// 抛弃
        } else {
            return false
        }
    })

return result
}

console.log( JSON.stringify(filterTree(raw), null, 4) )

// 打印结果
// [
//     {
//         "name": "A",
//         "children": [
//             {
//                 "name": "C",
//                 "children": [
//                     {
//                         "name": "E",
//                         "visible": true
//                     }
//                 ]
//             },
//             {
//                 "name": "D",
//                 "visible": true,
//                 "children": [
//                     {
//                         "name": "G"
//                     },
//                     {
//                         "name": "H"
//                     },
//                     {
//                         "name": "I"
//                     }
//                 ]
//             }
//         ]
//     }
// ]

其实也就十来行...

在线演示链接:https://jsfiddle.net/Roam/5jb0r8y5/
    tree.gif

总结

递归是个好东西,能省很多代码(让我想起一个面试题...淡淡的忧伤)
    代码写得不顺手,肯定哪里有问题

原文地址:https://www.cnblogs.com/dirgo/p/12357376.html

时间: 2024-08-03 22:58:20

[转]iView Cascader、Tree 数据处理的相关文章

iview中tree的事件运用

iview中的事件和方法如下: 案例说明: html代码 <Tree :data="data4" @on-check-change="choiceAll" ref="tree4" show-checkbox multiple></Tree> -------------------------------------------------------------------------------------------

iview Cascader级联选择省市区问题,并附上数据

vue项目中,用到了iview的Cascader级联选择省市区,之前用的是iview-area这个插件做的省市区下拉选择, 没啥大问题,就是选择省市区后,屏幕会抖动一下,体验不好,又找不到解决办法, 之后重新选择了iview中的Cascader <FormItem label="省市区:" prop="chinaArea"> <Cascader v-model="eroomInfo.chinaArea" :data="

iView的tree组件实现单选功能

iView中的树组件有复选框可以多选,但是目前还没有提供单选框的模式,不显示复选框可以提供高亮单选的模式,但是再次点击就被取消了,没有实现真正的单选: tree 的属性配置中 multiple 是否支持多选,是在不显示复选框的时候生效的,不能控制复选框支不支持多选: 实现单选功能中用到了: :show-checkbox="true"  // 是否显示复选框 :check-strictly="true" // 显示复选框的前提下,是否让父子节点不联动 :check-d

基于vue手写tree插件那点事

目录 iview提供的控件 手写控件 手写控件扩展 手写控件总结 # 加入战队 微信公众号 主题 Tree树形控件在前端开发中必不可少,对于数据的展示现在网站大都采取树形展示.因为大数据全部展示出来对于用户来说是不友好的.今天我们自己手写一个Tree插件. iview提供的控件 iview已经很成熟了,如果说我写的控件和iview提供的控件谁更好,那肯定是选择iview , 手写控件只是为了更好的了解vue父子组件之间的通信的. 请读者还是不要拿我的控件和iview或者其他第三方的去对比.下面我

2019-09-25,有感

好久没写,得有一个月了吧,这之间做了一个项目. /* 项目不大,但是做的很痛苦,需求乱,时间紧,关键功能全需要与外部项目对接,再加上外部项目的负责人不是很配合,哎,毕竟人家也很忙啊.  */ 作为后端,第一次搭建前端框架,发现有句话说的很对:“不逼自己一把,不知道自己有多牛逼.”. 这个项目,技术上其实没什么难度,但是我毕竟不是专业前端,也没有准确的界面要求,所以导致界面的颜色.缝隙高度宽度一直在调整,所以有些反复性工作. 也遇到了一些坑,爬出来之后,发现是自己挖的,所以不太想总结出来(都是泪啊

iview tree 获取选中子节点的整条数据链

这样子获取到数据是,checked等于true的,获取不到他的父级,父级的父级 解决办法代码如下: //需要有一个唯一ID //====================================== //扩展remove方法 Array.prototype.remove = function (val) { let index = this.indexOf(val); if (index > -1) { this.splice(index, 1); } }; //=============

iview tree 绑定数据

官方文档 :https://www.iviewui.com/components/tree 效果图 1 主体分析 <Tree ref="tree" :data="treeData" :load-data="loadData" :render="renderContent" :on-select-change="loadData"></Tree> :load-data=loadData

只是一个文件节点类为了项目的数据处理

已经研究生二年级下学期了,已经为了这个检索项目写了差不多2年代码了,回想大四下学期就开始接触的这个项目,在研一的时候根本不知道科研如何做,而且项目就自己一个人,也是胡乱写了代码,而且心事太多,简直只能用一个词语形容就是混乱. 但是在大二上学期10月份的时候,随着一位同学加入简直就是可以说这个项目才真正开始.在我们的系统完成后,我便心血来潮整理我之前写过的代码,因为我们要写论文,所以需要做很多的数据处理来完成实验对比部分,其实这部分数据处理我在大一的时候就已经写过类似的代码,结果现在不得不重新再写

第6章 物联网的数据处理

6.1 物联网数据处理技术的基本概念     6.1.1 物联网数据的特点 大规模存储系统的应用越来越广泛,存储容量也从以前的TB(Terabyte)级上升到PB(Petabyte)级甚至EB(Exabyte)级.随着存储系统规模不断增大,在大规模文件系统中,文件的数量高达几十亿个,在这种海量数据中查找和管理文件变得异常困难. 由于搜索引擎技术的发展,在互联网的环境下查找信息很方便,而用户在存储系统中找到想要的信息比在互联网上查找信息更加困难. 如今存储系统中的数据量的快速增长使得查找和管理文件