如何使用递归 Vue 循环创建 DevExtreme Multi-Level Headers?

How to create DevExtreme Multi-Level Headers using a recursive Vue loop?

我正在为我的 Vue3 应用程序使用 DevExtreme 组件。基于此示例 ( docs / code sample ),我想根据配置创建多级别 headers。我想我将不得不为此使用递归循环。

首先,我创建了一个组件 GridColumn 作为树中的一个节点,它能够在有或没有其嵌套 children

的情况下呈现自身
<template>
  <!-- If there are no children use the data-field prop -->
  <dx-column
    v-if="gridColumn.children === undefined"
    :caption="gridColumn.caption"
    :data-field="gridColumn.dataField"
  />
  <!-- If there are children nest them inside -->
  <dx-column v-else :caption="gridColumn.caption">
    <grid-column
      v-for="childGridColumn in gridColumn.children"
      :key="childGridColumn.caption"
      :gridColumn="childGridColumn"
    />
  </dx-column>
</template>

<script lang="ts">
import { DxColumn } from "devextreme-vue/data-grid";
import { defineComponent } from "vue";

export default defineComponent({
  name: "grid-column",
  components: {
    "dx-column": DxColumn,
  },
  props: {
    gridColumn: Object,
  },
});
</script>

现在我可以在 主页 视图中使用这个组件

<template>
  <dx-data-grid :data-source="data" :show-borders="true">
    <grid-column
      v-for="columnDefinition in columnDefinitions"
      :key="columnDefinition.caption"
      :gridColumn="columnDefinition"
    />
  </dx-data-grid>
</template>

<script lang="ts">
import DxDataGrid from "devextreme-vue/data-grid";
import { defineComponent, ref } from "vue";

import GridColumn from "../components/GridColumn.vue";

export default defineComponent({
  components: {
    "dx-data-grid": DxDataGrid,
    "grid-column": GridColumn,
  },
  setup() {
    const columnDefinitions = ref([
      {
        caption: "Col 1",
        dataField: "fieldOne",
      },
      {
        caption: "Col 2",
        children: [
          {
            caption: "Col 2.1",
            dataField: "fieldTwo",
          },
          {
            caption: "Col 2.2",
            dataField: "fieldThree",
          },
        ],
      },
      {
        caption: "Col 3",
        children: [
          {
            caption: "We need to go deeper",
            children: [
              {
                caption: "... deeper ...",
                children: [
                  {
                    caption: "... almost ...",
                    children: [
                      {
                        caption: "GO FOR IT",
                        dataField: "fieldFour",
                      },
                    ],
                  },
                ],
              },
            ],
          },
        ],
      },
    ]);

    const data = ref([
      {
        fieldOne: "foo",
        fieldTwo: 2,
        fieldThree: new Date(),
        fieldFour: { x: "y" },
      },
      {
        fieldOne: "some more text",
        fieldTwo: 123,
        fieldThree: new Date(),
        fieldFour: { a: "b" },
      },
    ]);

    return { columnDefinitions, data };
  },
});
</script>

渲染结果将是

这不是我想要的,字幕有误,缺少 parent headers。您可以查看 sandbox demo here

只是为了展示我想要实现的目标

工作 sandbox demo

有人知道我的实现有什么问题吗?也许还有更简单的解决方案?

我没有找到递归元素的解决方案,但您可以在 data-table 本身上使用 columns 属性。

你的 data-table 看起来像这样

<dx-data-grid 
  :data-source="data" 
  :show-borders="true"
  :columns="columnDefinitions">
</dx-data-grid>

现在您只需将 children 数组重命名为 columns

const columnDefinitions = ref([
  {
    caption: "Col 1",
    dataField: "fieldOne",
  },
  {
    caption: "Col 2",
    columns: [
      {
        caption: "Col 2.1",
        dataField: "fieldTwo",
      },
      {
        caption: "Col 2.2",
        dataField: "fieldThree",
      },
    ],
  },
  {
    caption: "Col 3",
    columns: [
      {
        caption: "We need to go deeper",
        columns: [
          {
            caption: "... deeper ...",
            columns: [
              {
                caption: "... almost ...",
                columns: [
                  {
                    caption: "GO FOR IT",
                    dataField: "fieldFour",
                  },
                ],
              },
            ],
          },
        ],
      },
    ],
  },
]);

我能找到的唯一提到 columns 属性 的文档是 here。不过,关于如何在 vue 中使用它并不是很明确。