码农-小林 2025-07-16 09:25 采纳率: 54.8%
浏览 10
已结题

使用typescript声明数组结合vuex后使用嵌套for获取数据丢失

1,使用声明文件

declare namespace DeviceTree {
  interface firstFloor {
    province: string, // 省份
    citys: DeviceTree.secondFloor[]
  }

  interface secondFloor {
    city: string, // 城市
    voltages: DeviceTree.thirdFloor[]
    lines: DeviceTree.fourthFloor[]
  }

  interface thirdFloor {
    voltage: string, // 电压
    lines: DeviceTree.fourthFloor[]
  }

  interface fourthFloor {
    lineId: string,
    name: string, // 线路
    tower: DeviceTree.fifthFloor[],
    desc: any // 描述
    endLocation: any // 结束位置
    startLocation: any // 起始位置
    title:string
  
  }

 // interface fifthFloor {
  // towerName: string // 杆塔
   // devices: DeviceTree.sixthFloor[]
    
 // }

  interface sixthFloor {
    devices: DeviceTree.sixthFloor[]
    deviceId: string,
    name: string, // 设备名称
    type: any
    channelModelList:DeviceTree.seventhFloor[]
  }
  interface seventhFloor {
    deviceId: string,
    channel: number, // 通道
    // type: any
  }
  interface antTree {
    title: string,
    key: string,
    children: DeviceTree.antTree[],
    parentKey?: stringp[]
    [propname: string]: any
  }
}

2,这是写的树文件

 getDeviceTree().then((res: any) => {
      const tree = this.buildFirstFloorData(res.data,false);
      this.$store.commit("SET_DEVICE_TREE_DATA", tree);
      const channelTree = this.buildFirstFloorData(res.data,true);
      this.$store.commit("SET_DEVICE_CHANNEL_TREE_DATA", channelTree);
    });


  }
  // 构建第一层设备树结构(在buildFifthFloorData层使用嵌套获取数据后,会丢失几个devices数组里面数据)
  buildFirstFloorData(
    data: DeviceTree.firstFloor[],
    channelShow:boolean,
    treeData: DeviceTree.antTree[] = []
  ) {
    for (let i = 0; i < data.length; i++) {
      var provinces=data[i].province.split("(")[0]
      if(/.*[\u4e00-\u9fa5]+.*$/.test(provinces)){
      provinces=data[i].province
      }else{
        provinces=Base64.decode(data[i].province.split("(")[0])+"("+data[i].province.split("(")[1]
      }
      const onlyId = createdOnlyId();
      const treeNode: DeviceTree.antTree = {
        title: provinces, // 省份
        key: onlyId,
        children: [],
        scopedSlots: {
          icon: "icon",
        },
        icon: require("@/assets/device-tree/province-icon.png"),
      };
      treeData[i] = treeNode;
      this.treeNode.push(treeNode); // 把节点添加到树节点列表中
      this.buildSecondFloorData(data[i].citys, treeData[i].children, [onlyId],channelShow);
    }
    this.commitToVuex();
    return treeData;
  }

  // 把数据存到vuex
  commitToVuex() {
    this.$store.commit("SET_TREE_NODE_LIST", this.treeNode);
    this.$store.commit("SET_DEVICE_LIST", this.deviceList);
    this.$store.commit("SET_LINE_LIST", this.lineList);
  }

  // 构建第二层设备树结构
  buildSecondFloorData(
    data: DeviceTree.secondFloor[],
    treeData: DeviceTree.antTree[],
    parentKey: string[],
    channelShow:boolean
  ) {
    for (let i = 0; i < data.length; i++) {
     var citys=data[i].city.split("(")[0]
      if(/.*[\u4e00-\u9fa5]+.*$/.test(citys)){
        citys=data[i].city
      }else{
        citys=Base64.decode(data[i].city.split("(")[0])+"("+data[i].city.split("(")[1]
      }
      const onlyId = createdOnlyId();
      const treeNode: DeviceTree.antTree = {
        title:citys, // 城市
        key: onlyId,
        children: [],
        scopedSlots: {
          icon: "icon",
        },
        icon: require("@/assets/device-tree/city-icon.png"),
        parentKey,
      };
      treeData[i] = treeNode;
      this.treeNode.push(treeNode); // 把节点添加到树节点列表中
      this.buildThirdFloorData(
        data[i].voltages,
        treeData[i].children,
        parentKey.concat(onlyId),
        channelShow
      );
    }
  }

  // 构建第三层设备树结构
  buildThirdFloorData(
    data: DeviceTree.thirdFloor[],
    treeData: DeviceTree.antTree[],
    parentKey: string[],
    channelShow:boolean
  ) {
    for (let i = 0; i < data.length; i++) {
      const onlyId = createdOnlyId();
      const treeNode: DeviceTree.antTree = {
        title: data[i].voltage, // 电压
        key: onlyId,
        children: [],
        parentKey,
      };
      treeData[i] = treeNode;
      this.treeNode.push(treeNode); // 把节点添加到树节点列表中
      this.buildFourthFloorData(
        data[i].lines,
        treeData[i].children,
        parentKey.concat(onlyId),
        channelShow
      );
    }
  }

  // 构建第四层设备树结构
  buildFourthFloorData(
    data: DeviceTree.fourthFloor[],
    treeData: DeviceTree.antTree[],
    parentKey: string[],
    channelShow:boolean
  ) {
    for (let i = 0; i < data.length; i++) {
      const onlyId = createdOnlyId();
      const treeNode: DeviceTree.antTree = {
        title: data[i].name, // 线路名称
        key: onlyId,
        children: [],
        scopedSlots: {
          icon: "icon"
        },
        lineIcon: true,
        lineId: data[i].lineId, // 线路id
        desc: data[i].desc,
        startLocation:data[i].startLocation ,//data[i].startLocation
        endLocation: data[i].endLocation,//data[i].endLocation
        parentKey,
      };
 
      treeData[i] = treeNode;
      this.treeNode.push(treeNode); // 把节点添加到树节点列表中

      this.lineList = this.lineList.concat(treeNode); // 把线路添加到线路列表中
     // for (let j = 0; j < data[i].tower.length; j++) {
      this.buildFifthFloorData(
        data[i].tower,
        treeData[i].children,
        parentKey.concat(onlyId),
        channelShow
      );
      //  }
    }
  }

  // 构建第五层设备树结构
  buildFifthFloorData(
    data: DeviceTree.sixthFloor[],
    treeData: DeviceTree.antTree[],
    parentKey: string[],
    channelShow:boolean
  ) {
    for (let i = 0; i < data.length; i++) {
      //在这里试下循环看看可不可以直接获取设备显示
        for (let j = 0; j < data[i].devices.length; j++) {
        var state = data[i].devices[j]["onlineState"]==4 ?  2: 1;
        const onlyId = createdOnlyId();
        const treeNode: DeviceTree.antTree = {
        title: data[i].devices[j].name, // 杆塔名称
        key: createdOnlyId(),
        children: [],
        scopedSlots: {
          icon: "icon",
        },
       icon: require(`@/assets/device-tree/device-icon-${data[i].devices[j].type}-${state}.png`),
        parentKey,
      };
      treeData[j] = treeNode;
      this.treeNode.push(treeNode); // 把节点添加到树节点列表中
      this.buildSeventhFloorData(
        data[i].devices[j].channelModelList,
        treeData[j].children,
        parentKey.concat(onlyId),
        data[i].devices[j].name
      );
        }
    }
  }

  // 构建第六层设备树结构
 /* buildSixthFloorData(
    data: DeviceTree.sixthFloor[],
    treeData: DeviceTree.antTree[],
    parentKey: string[],
    channelShow:boolean
  ) {
    
    for (let i = 0; i < data.length; i++) {
  
      const onlyId = createdOnlyId();
      var state = data[i]["onlineState"]==4 ?  2: 1;
      const treeNode: DeviceTree.antTree = {
        title: data[i].name, // 杆塔名称
        key: onlyId,
        children: [],
        deviceId: data[i].deviceId,
        scopedSlots: {
          icon: "icon",
        },
        icon: require(`@/assets/device-tree/device-icon-${data[i].type}-${state}.png`),
        parentKey,
      };
      treeData[i] = treeNode;
      this.treeNode.push(treeNode); // 把节点添加到树节点列表中
      if(channelShow){
        this.deviceList = this.deviceList.concat(treeNode); // 把设备添加到设备列表中
        // console.log( this.deviceList)
        this.buildSeventhFloorData(
        data[i].channelModelList,
        treeData[i].children,
        parentKey.concat(onlyId),
        data[i].name
      );
      }
      
    }
  }*/

  // 构建第七层设备树结构
  buildSeventhFloorData(
    data: DeviceTree.seventhFloor[],
    treeData: DeviceTree.antTree[],
    parentKey: string[],
    deviceName:String,
  ) {   
    for (let i = 0; i < data.length; i++) {
      const treeNode: DeviceTree.antTree = {
        title: deviceName+"-"+String(data[i].channel), // 通道
        deviceId: data[i].deviceId,
        channel:data[i].channel,
        key: createdOnlyId(),
        children: [],
        parentKey,
      };
      treeData[i] = treeNode;
      this.treeNode.push(treeNode); // 把节点添加到树节点列表中
    }



  • 写回答

6条回答 默认 最新

  • 檀越@新空间 2025-07-16 09:26
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    在您提供的代码中,您使用了 TypeScript 声明文件来定义设备树结构,并通过 buildFirstFloorDatabuildSecondFloorDatabuildThirdFloorData 等方法构建树结构。但在使用嵌套 for 循环获取数据时,出现了数据丢失的问题


    问题分析

    1. 嵌套 for 循环中使用数组赋值方式不安全
      您在 buildFirstFloorData 中直接对 treeData[i] = treeNode; 进行赋值,这可能导致索引越界或覆盖其他数据。

    2. 未正确使用 push 添加元素
      在构建树结构时,应该使用 push() 方法将新节点添加到数组中,而不是直接赋值给特定索引。

    3. 可能的引用传递问题
      如果多个层级之间共享同一个对象(如 treeNode),可能会导致数据被覆盖。

    4. 未处理异步操作和数据完整性
      您在 getDeviceTree().then(...) 中调用 buildFirstFloorDatabuildChannelTree,但没有确保数据完全构建后再提交到 Vuex。


    解决方案

    1. 使用 push() 替代直接索引赋值

    在构建每一层的 treeData 时,应使用 push() 而不是 treeData[i] = ...,以避免索引越界和数据覆盖。

    修改后的 buildFirstFloorData 示例:

    buildFirstFloorData(
      data: DeviceTree.firstFloor[],
      channelShow: boolean,
      treeData: DeviceTree.antTree[] = []
    ) {
      for (let i = 0; i < data.length; i++) {
        var provinces = data[i].province.split("(")[0];
        if (/.*[\u4e00-\u9fa5]+.*$/.test(provinces)) {
          provinces = data[i].province;
        } else {
          provinces = Base64.decode(data[i].province.split("(")[0]) + "(" + data[i].province.split("(")[1];
        }
        const onlyId = createdOnlyId();
        const treeNode: DeviceTree.antTree = {
          title: provinces, // 省份
          key: onlyId,
          children: [],
          scopedSlots: {
            icon: "icon",
          },
          icon: require("@/assets/device-tree/province-icon.png"),
        };
        treeData.push(treeNode); // ✅ 使用 push() 添加节点
        this.treeNode.push(treeNode); // 把节点添加到树节点列表中
        this.buildSecondFloorData(data[i].citys, treeData[treeData.length - 1].children, [onlyId], channelShow);
      }
      this.commitToVuex();
      return treeData;
    }
    

    2. 确保每层构建完成后才进行下一层构建

    在构建第二层、第三层等时,应确保当前层的数据已完整构建后再进入下一层,避免因异步或逻辑错误导致数据丢失。

    修改后的 buildSecondFloorData 示例:

    buildSecondFloorData(
      data: DeviceTree.secondFloor[],
      treeData: DeviceTree.antTree[],
      parentKey: string[],
      channelShow: boolean
    ) {
      for (let i = 0; i < data.length; i++) {
        var citys = data[i].city.split("(")[0];
        if (/.*[\u4e00-\u9fa5]+.*$/.test(citys)) {
          citys = data[i].city;
        } else {
          citys = Base64.decode(data[i].city.split("(")[0]) + "(" + data[i].city.split("(")[1];
        }
        const onlyId = createdOnlyId();
        const treeNode: DeviceTree.antTree = {
          title: citys, // 城市
          key: onlyId,
          children: [],
          scopedSlots: {
            icon: "icon",
          },
          icon: require("@/assets/device-tree/city-icon.png"),
          parentKey,
        };
        treeData.push(treeNode); // ✅ 使用 push() 添加节点
        this.treeNode.push(treeNode); // 把节点添加到树节点列表中
        this.buildThirdFloorData(
          data[i].voltages,
          treeData[treeData.length - 1].children,
          parentKey.concat(onlyId),
          channelShow
        );
      }
    }
    

    3. 避免重复引用对象

    如果多个层级之间共享相同的 treeNodetreeData,可能会导致数据覆盖。建议每次构建新的节点对象。


    4. 确保数据完整后再提交到 Vuex

    buildFirstFloorData 中,应确保所有层级构建完成后再调用 commitToVuex(),避免数据未完全生成就提交到 Store。

    修改后的 buildFirstFloorData 示例(确保构建完成):

    buildFirstFloorData(
      data: DeviceTree.firstFloor[],
      channelShow: boolean,
      treeData: DeviceTree.antTree[] = []
    ) {
      for (let i = 0; i < data.length; i++) {
        // 构建省份节点并添加到 treeData
        // ...
        this.buildSecondFloorData(data[i].citys, treeData[treeData.length - 1].children, [onlyId], channelShow);
      }
    
      // ✅ 确保所有层级构建完成后再提交
      this.commitToVuex();
    
      return treeData;
    }
    

    5. 使用 TypeScript 类型强化数据结构

    确保 buildFirstFloorDatabuildSecondFloorData 等函数返回类型正确,防止运行时类型错误。

    示例:

    buildFirstFloorData(
      data: DeviceTree.firstFloor[],
      channelShow: boolean,
      treeData: DeviceTree.antTree[] = []
    ): DeviceTree.antTree[] {
      // ...
      return treeData;
    }
    

    总结

    重点解决方案:

    1. 使用 push() 替代直接索引赋值,避免数据覆盖。
    2. 确保每层构建完成后才进入下一层,避免异步问题。
    3. 避免重复引用对象,防止数据丢失。
    4. 在所有层级构建完成后才提交到 Vuex,保证数据完整性。
    5. 使用 TypeScript 类型强化数据结构,提升代码健壮性。

    如果您需要进一步优化代码结构或实现更复杂的树形数据处理,也可以考虑引入递归函数或使用工具库(如 lodashmap, reduce 等)简化嵌套逻辑。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

问题事件

  • 系统已结题 7月24日
  • 已采纳回答 7月16日
  • 创建了问题 7月16日