You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js 3中对象数组转CSV文件失败,求修复方案

修复对象数组转CSV并下载的问题

核心问题分析

  • 原arrayToCsv函数是为二维数组设计的,但你传入的是对象数组,导致每个对象被直接转为[object Object],输出完全不符合预期。
  • 嵌套对象pick未做特殊处理,直接转字符串会丢失内部数据。
  • 下载文件名里的./属于无效前缀,浏览器下载时会自动忽略。

修复方案

方案1:保留嵌套对象(转为JSON字符串)

适合需要保留原数据结构的场景,嵌套对象会以JSON格式存入CSV列中:

<template>
  <div @click="saveLogs()">save csv</div>
</template>

<script>
export default {
  name: "App",
  components: {},
  methods: {
    arrayToCsv(data) {
      if (!data.length) return '';
      // 提取对象键作为CSV表头
      const headers = Object.keys(data[0]);
      // 处理每行数据:转义引号、包裹字段、处理嵌套对象
      const rows = data.map(row => {
        return headers.map(key => {
          let value = row[key];
          // 嵌套对象转为JSON字符串
          if (typeof value === 'object' && value !== null) {
            value = JSON.stringify(value);
          }
          // 转义双引号并包裹字段
          value = String(value).replaceAll('"', '""');
          return `"${value}"`;
        }).join(',');
      });
      // 拼接表头和行数据
      return [headers.join(','), ...rows].join('\r\n');
    },
    downloadBlob(content, filename, contentType) {
      const blob = new Blob([content], { type: contentType });
      const url = URL.createObjectURL(blob);
      const pom = document.createElement("a");
      
      pom.href = url;
      pom.setAttribute("download", filename);
      // 兼容部分浏览器,需临时添加到DOM
      document.body.appendChild(pom);
      pom.click();
      document.body.removeChild(pom);
      URL.revokeObjectURL(url); // 释放URL资源,避免内存泄漏
    },
    saveLogs() {
      const logData = [
        { act_id: 44, actor: "robot_arm", color: "yellow", lego: "yb1", pick: {x: 1, y: 2, z:5} },
        { act_id: 44, actor: "robot_arm", color: "yellow", lego: "yb2", pick: {x: 1, y: 2, z:5} },
      ];
      const myLogs = this.arrayToCsv(logData);
      this.downloadBlob(myLogs, "gui_logs.csv", "text/csv;charset=utf-8;");
      console.log("Logs has been saved");
    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

方案2:展开嵌套对象(拆分为独立列)

适合需要在表格工具中直接查看嵌套字段的场景,嵌套对象的键会被展开为pick_x、pick_y这类表头:

<template>
  <div @click="saveLogs()">save csv</div>
</template>

<script>
export default {
  name: "App",
  components: {},
  methods: {
    // 递归展开嵌套对象
    flattenObject(obj, parentKey = '') {
      let result = {};
      for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
          const newKey = parentKey ? `${parentKey}_${key}` : key;
          if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
            Object.assign(result, this.flattenObject(obj[key], newKey));
          } else {
            result[newKey] = obj[key];
          }
        }
      }
      return result;
    },
    arrayToCsv(data) {
      if (!data.length) return '';
      // 先展开所有嵌套对象
      const flattenedData = data.map(item => this.flattenObject(item));
      // 提取展开后的表头
      const headers = Object.keys(flattenedData[0]);
      // 处理每行数据
      const rows = flattenedData.map(row => {
        return headers.map(key => {
          let value = row[key];
          value = String(value).replaceAll('"', '""');
          return `"${value}"`;
        }).join(',');
      });
      return [headers.join(','), ...rows].join('\r\n');
    },
    downloadBlob(content, filename, contentType) {
      const blob = new Blob([content], { type: contentType });
      const url = URL.createObjectURL(blob);
      const pom = document.createElement("a");
      
      pom.href = url;
      pom.setAttribute("download", filename);
      document.body.appendChild(pom);
      pom.click();
      document.body.removeChild(pom);
      URL.revokeObjectURL(url);
    },
    saveLogs() {
      const logData = [
        { act_id: 44, actor: "robot_arm", color: "yellow", lego: "yb1", pick: {x: 1, y: 2, z:5} },
        { act_id: 44, actor: "robot_arm", color: "yellow", lego: "yb2", pick: {x: 1, y: 2, z:5} },
      ];
      const myLogs = this.arrayToCsv(logData);
      this.downloadBlob(myLogs, "gui_logs.csv", "text/csv;charset=utf-8;");
      console.log("Logs has been saved");
    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

内容的提问来源于stack exchange,提问作者Bilal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 10:46:16