element,cascader数据多选,数据处理(返回给后端,回填数据)

数据处理

思路:
1.先创建必要的函数: 数组打平flat,递归树(deepTree),模板(temp)
2.发送数据:首先把你选择的数据格式, deepTreeData(tree, flat(selectedTree), [‘id’]) 选择的数据格式,
3.然后转换成发送的格式, sendSelectedData(tree, flat(selectedTree), [‘id’, ‘name’])
4.回填数据:把发送的数据打平, splitArr(sendSelectedData(tree, flat(selectedTree)), [‘id’]
5.转换成选中的格式 deepTreeData(tree, flat(selectedTree), [‘id’])

方法一:

  // // 原始数据
        let tree = [{
                id: 1,
                name: "测试",
                children: [{
                        id: 11,
                        name: '测试11',
                        children: [{
                                id: 11113,
                                name: '测试11'
                            },
                            {
                                id: 11111113,
                                name: '测试12'
                            }
                        ]
                    },
                    {
                        id: 12,
                        name: '测试12'
                    }
                ]
            },
            {
                id: 2,
                name: "测试",
                children: [{
                        id: 21,
                        name: '测试21'
                    },
                    {
                        id: 22,
                        name: '测试22'
                    }
                ]
            }
        ]
        // 选择的数据
        let selectedTree = [
            [1, 11, 12, 11111113, 11113],
            [2, 21]
        ]
        //要发送的数据格式
        // [{
        //     id: 1,
        //     name: '测试'
        // }]

        // 思路:
        // 1.先创建必要的函数: 数组打平flat,递归树(deepTree),模板(temp)
        // 2.发送数据:首先把你选择的数据格式, deepTreeData(tree, flat(selectedTree), ['id'])   选择的数据格式,
        // 3.然后转换成发送的格式,  sendSelectedData(tree, flat(selectedTree), ['id', 'name'])
        // 4.回填数据:把发送的数据打平, splitArr(sendSelectedData(tree, flat(selectedTree)), ['id']
        // 5.转换成选中的格式  deepTreeData(tree, flat(selectedTree), ['id'])



   		console.log("-------------原始全部数据-----------------")
        console.log(tree)



        console.log("-------------选中原始数据-----------------")
        console.log(selectedTree)




        // 数组打平
        function flat(tree) {
            if (!Array.isArray(tree)) return
           return tree.flat(Infinity)

        }
        console.log("-------------选中的数据打平-----------------")
        console.log(flat(selectedTree))


        // 返回数据的格式

        function temp(arr, data) {
            let copyObj = {}
            if (arr.length > 1) {
                arr.forEach(item => {
                    copyObj[item] = data[item]
                })
                return copyObj
            } else {
                return data[arr[0]]
            }
        }


        // 递归使用tree(已经选中,获取对应的键值对)
        var copySelected = []

        function deepTree(tree, selectedTree, arr = ['id', 'name']) {
            tree.forEach(item => {
                selectedTree.includes(item.id) ? copySelected.push(temp(arr, item)) : ''
                if (item.children) {
                    deepTree(item.children, selectedTree, arr)
                }
            });
        }



        // 回填选中数据
        function deepTreeData(tree, selectedTree, arr = ['id', 'name']) {
            let selected = []
            
            
            tree.forEach(item => {
                copySelected = []
                selectedTree.includes(item.id) ? copySelected.push(temp(arr, item)) : ''
                deepTree(item.children, selectedTree, arr)

                selected.push([...copySelected])
            })
            return selected
        }

        // 发送的数据需要的格式

        function sendSelectedData(tree, selectedTree, arr1) {
            let copyData = []
            let data = deepTreeData(tree, selectedTree, arr1)
            data.forEach(item => {
                item.forEach(innerItem => {
                    copyData.push(innerItem)
                })
            })
            return copyData
        }


        console.log("-------------要发送的数据-----------------")
        console.log(sendSelectedData(tree, flat(selectedTree), ['id', 'name']))





        // 拆分
        function splitArr(data, id) {
            return data.map(item => {
                return item[id]
            })
        }

        console.log("-------------回填数据打平-----------------")
        console.log(splitArr(sendSelectedData(tree, flat(selectedTree)), ['id']))






        console.log("-------------渲染数据-----------------")

        let arr = deepTreeData(tree, flat(selectedTree), ['id'])

        console.log((arr))
        

在这里插入图片描述

方法二:





        let str = '12###234,34###345'




        let strArr = [
            [1, 2],
            [4, 5]
        ]

        function splitArr(dataStr) {
            let strCopy = dataStr.split(',')
            return strCopy = strCopy.map(item => {
                return item.split('###')

            });
        }

        function splitStr(dataArr) {
            let dataArrCopy = ''
            dataArr.map(item => {
                const innerStr = item.join('###')
                dataArrCopy+=','+innerStr
                
            })
            return dataArrCopy.slice(1)
            
        }

        console.log(splitArr(str))
        console.log(splitStr(strArr))

在这里插入图片描述

<think>我们正在讨论的是ElementPlus的级联择器(Cascader)的懒加载功能。根据用户的问题和之前的引用,我们需要解释如何实现懒加载,并解决可能遇到的问题(如搜索、回填等)。以下将分步骤说明:###1.理解懒加载在Cascader中的作用在ElementPlus的Cascader级联择器中,懒加载(lazy)用于动态加载项。当数据量很大(如省市区数据)时,一次性加载所有层级数据会导致性能问题。懒加载允许在用户展开某一层级时,才通过异步请求加载该层级的子项。###2.基本使用步骤####2.1启用懒加载在Cascader组件中,设置`props`属性的`lazy`为`true`,并指定`lazyLoad`方法作为加载函数。```vue<template><el-cascaderv-model="selectedValues":props="props"/></template><scriptsetup>import{ref}from'vue';constselectedValues=ref([]);//绑定选中的值constprops=ref({lazy:true,lazyLoad(node,resolve){//node:当前点击的节点//resolve:回调函数,用于返回子节点数据//根据node.level判断当前层级,node.data是当前节点的数据//执行异步请求,获取子节点数据,然后调用resolve返回const{level,data}=node;//示例:假设根据父节点的id请求子节点fetchChildren(data?.value||null).then(children=>{resolve(children);//注意:children数组中的对象格式需符合要求});}});//模拟异步请求functionfetchChildren(parentId){//根据parentId请求子节点数据//返回一个Promise,解析为子节点数组//示例数据格式:[{value:'1',label:'北京',leaf:false},...]returnnewPromise(resolve=>{//这里实际应使用ajax或axios请求setTimeout(()=>{if(parentId===null){//第一级(省)resolve([...]);//返回省份数组}else{//下一级(市/区等)resolve([...]);//返回子级数组}},300);});}</script>```####2.2节点对象的格式每个节点对象应包含以下属性:-`label`:显示的文本-`value`:节点的值-`leaf`:是否为叶子节点(即没有子节点),如果还有下级,则设为`false`,这样当用户点击时才会触发`lazyLoad`###3.解决引用中提到的常见问题####3.1搜索功能不可用(引用[1])在懒加载模式下,`filterable`搜索功能默认不可用,因为Cascader没有全量数据。解决方案:-自定义搜索逻辑:使用`filter-method`属性,结合每个层级的单独搜索接口。```vue<el-cascader:filterable="true":filter-method="filterMethod":props="props"v-model="selectedValues"/>```在`filterMethod`中,需要根据输入的关键字,递归地搜索所有层级的数据(通常需要调用搜索接口)。参考代码:```javascriptfunctionfilterMethod(node,keyword){//根据关键字过滤,返回一个Promise//可以调用一个统一的搜索接口,返回匹配的节点路径returnnewPromise(resolve=>{searchNodes(keyword).then(paths=>{//paths:匹配的完整路径数组//每个路径是一个节点数组(从根到叶子)resolve(paths);});});}```注意:这种方式需要后端支持一个全局搜索接口,返回匹配的路径。####3.2回填问题(引用[2])在懒加载模式下,回填初始值时,需要确保每个节点的`leaf`属性正确设置,并且节点路径完整。如果初始值是一个数组(),需要:1.通过初始值(通常是叶子节点的value数组)反查完整路径。2.在组件加载时,预先加载这些路径上的节点。具体实现:-在`created`或`mounted`钩子中,根据初始值数组,逐个获取其路径(通过接口或已有数据)。-将路径设置到Cascader的`node`中,确保回显。参考引用[4]中的回显思路:由于Cascader接收的v-model是数组格式(每个择路径的叶子节点的值组成的数组),但在懒加载模式下,要显示完整的路径标签,需要预先加载这些路径的各级节点。```javascript//假设初始值是一个数组:['value1','value2'](时,每个选中的叶子节点值)//需要将它们转换为路径数组:[[根节点值,子节点值,...,叶子节点值],...]//在created中处理created(){this.selectedValues=...;//初始值数组()//遍历初始值,获取每个值对应的完整路径this.selectedValues.forEach(value=>{this.fetchNodePath(value).then(path=>{//将路径中的每个节点预先加载到Cascader的节点树中//这通常需要修改内部状态,但ElementPlus没有直接提供API//因此,一种做法是将这些路径合并成一个数组,然后赋值给一个临时变量,再结合v-for强制重新渲染(不推荐)//另一种做法是在lazyLoad中判断当前节点是否需要加载(如果节点在预加载路径中,则提前加载)});});}```另一种简化方法(推荐):使用Cascader的`options`属性预先设置已知的路径节点(即使懒加载,也可以预先设置部分节点)。但需要确保节点结构符合要求。####3.3权限控制(引用[3])在懒加载时控制权限,可以在`lazyLoad`方法中根据用户权限过滤节点。比如:```javascriptlazyLoad(node,resolve){fetchChildren(node.data?.value).then(list=>{//根据当前用户的权限过滤节点constallowedList=list.filter(item=>checkPermission(userPermissions,item.value));resolve(allowedList);});}```###4.完整示例(省市区懒加载)参考引用[4],以下是一个省市区街道的懒加载实现:```vue<template><el-cascaderv-model="selectedPath":props="cascaderProps"/></template><scriptsetup>import{ref}from'vue';constselectedPath=ref([]);//选中的路径,如:['省id','市id','区id']constcascaderProps=ref({lazy:true,lazyLoad(node,resolve){const{level,data}=node;constparentId=level===0?0:data.value;//假设第一级的父id为0//获取下一级区域列表getRegionList(parentId).then(res=>{constnodes=res.map(item=>({value:item.id,label:item.name,leaf:level>=2//省市区三级,街道是第四级?这里根据层级判断叶子节点//如果还有下级,则leaf为false,否则为true}));resolve(nodes);});}});asyncfunctiongetRegionList(parentId){//调用后端接口,根据parentId获取子区域//返回类似:[{id:1,name:'北京市'},...]//实际使用axios等returnfetch(`/api/regions?parentId=${parentId}`).then(res=>res.json());}</script>```对于回显问题,如果selectedPath在初始时就有值(如`['1','2','3']`),需要确保在组件加载时,这些路径的节点已经被加载(在懒加载中,当父节点展开时才会加载子节点,所以回显时需要节点已经存在)。解决方案是在创建组件后,根据selectedPath的值逐级加载节点(递归或循环),并构建节点树。###5.总结-**懒加载核心**:设置`lazy:true`和`lazyLoad`方法。-**搜索支持**:自定义`filter-method`,并配合全局搜索接口。-**回填**:初始化时根据初始值获取完整路径并预先加载节点。-**权限控制**:在`lazyLoad`中过滤节点。###相关问题1.如何解决ElementPlusCascader懒加载模式下的搜索问题?2.ElementPlusCascader模式下如何正确回显初始值?3.如何在懒加载Cascader中实现动态权限控制?4.懒加载Cascader数据量极大时的性能优化方法?</think> ### Element Plus Cascader 懒加载实现方法 Element Plus 的 Cascader 级联择器在懒加载模式下,通过动态加载数据来优化性能,特别适合处理层级大数据量(如省市区择)的场景[^4]。以下是完整实现步骤: #### 1. 基本配置 ```vue <template> <el-cascader v-model="selectedValue" :props="cascaderProps" :show-all-levels="false" placeholder="请择" /> </template> <script setup> import { ref } from 'vue'; const selectedValue = ref([]); // 存储选中值,格式为数组 ['省ID', '市ID', '区ID'] const cascaderProps = ref({ lazy: true, // 启用懒加载 async lazyLoad(node, resolve) { const { level, data } = node; const parentId = level === 0 ? null : data.value; // 1. 根据层级获取数据 const result = await fetchRegionData(parentId); // 2. 构建节点数组 const nodes = result.map(item => ({ label: item.name, value: item.id, leaf: item.level >= 3 // 例如:3级是叶子节点(区县) })); // 3. 返回节点数据 resolve(nodes); } }); // 模拟API请求 const fetchRegionData = async (parentId) => { // 实际项目中使用axios/fetch调用API return [ { id: 1, name: '浙江省', level: 1 }, { id: 2, name: '江苏省', level: 1 } ]; }; </script> ``` #### 2. 核心参数说明 | 参数 | 类型 | 说明 | |--------------|------------|----------------------------------------------------------------------| | **lazy** | Boolean | 是否启用懒加载模式(必需设为`true`) | | **lazyLoad** | Function | 节点加载函数,接收两个参数: | | | | - `node`: 当前节点对象(包含`level`, `data`等属性) | | | | - `resolve`: 回调函数,用于返回子节点数据 | | **leaf** | Boolean | 节点属性,标记是否为叶子节点(无子节点) | #### 3. 数据回显处理(重点) 当需要显示已存储的值(如编辑时回填数据),需通过API获取完整路径[^4]: ```javascript import { onMounted } from 'vue'; // 假设从API获取的已存储数据:['1','101','1001'] const initValue = ref(['1','101','1001']); onMounted(async () => { // 1. 获取完整路径节点 const fullPath = await fetchFullPath(initValue.value); // 2. 构建回显数据结构 cascaderProps.value.initData = buildTree(fullPath); }); const buildTree = (pathArray) => { // 按层级构建节点树(需要根据API返回结构处理) return [{ value: '1', label: '浙江', children: [{ value: '101', label: '杭州', children: [{ value: '1001', label: '西湖区', leaf: true }] }] }]; }; ``` #### 4. 常见问题解决方案 1. **搜索功能失效**[^1] ```vue <el-cascader filterable :filter-method="customFilter" /> ``` ```javascript const customFilter = (input, path) => { return path.some(option => option.label.toLowerCase().includes(input.toLowerCase()) ); }; ``` 2. **值重复问题**[^2] ```javascript // 确保不同层级值不重复 [ { id: 1, name: "部署", level: 2, uniqueValue: "deploy-1" }, { id: 2, name: "部署", level: 3, uniqueValue: "deploy-2" } ] ``` 3. **权限控制**[^3] ```javascript lazyLoad(node, resolve) { fetchData(node).then(data => { resolve(data.filter(item => hasPermission(currentUser, item.id) // 过滤无权限项 )); }); } ``` ### 最佳实践建议 1. **后端API要求**: - 提供按父ID查询子节点的接口:`GET /regions?parentId=xxx` - 提供路径反查接口:`GET /regions/path?id=xxx` 返回完整路径ID数组 2. **性能优化**: ```javascript // 添加防抖避免频繁请求 import { debounce } from 'lodash-es'; lazyLoad: debounce(function(node, resolve) { // 加载逻辑 }, 300) ``` 3. **数据结构规范**: ```typescript interface Region { id: string | number name: string level: number // 1=省,2=市,3=区 parentId?: string | number } ``` [完整示例代码](https://element-plus.org/en-US/component/cascader.html#lazy-loaded)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值