首页 > 解决方案 > 组件内的 Vue 组件渲染表格不正确

问题描述

我有 2 个组件。

  1. 表组件
  2. 行组件(表格中的每一行)

表格组件<tbody>为数据中的每一行调用标签内的行组件。但是在渲染行时首先渲染(在表格标签之外),然后是<table>标签。

请参见下面的示例。

Vue.component('single-table-row', {
  props: {
    row: {
      type: Object
    }
  },
  template: `
    <tr>
    <td>{{row.id}}</td>
    <td>{{row.text}}</td>
    </tr>
  `
});

Vue.component('mytable', {
  props: {
    tabledata: {
      type: Object
    }
  },
  data: function () {
    return {
      headers: ['Id', 'Text']
    }
  },
  computed: {
    table_rows: function () {
      return this.tabledata.data.rows;
    }
  }
});

var app3 = new Vue({
  el: '#app-3',
  data: {
    mydata: {
      data: {
        rows: [
          {
            id: 1,
            text: 'Sample 1'
          },
          {
            id: 2,
            text: 'Sample 2'
          },
          {
            id: 3,
            text: 'Sample 3'
          }
        ]
      }
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app-3">
  <mytable v-bind:tabledata="mydata" inline-template>
    <div id="table_parent">
      <table>
        <thead>
          <tr>
            <th v-for="header in headers">{{header}}</th>
          </tr>
        </thead>
        <tbody>
          <single-table-row :row=rows v-for="rows in table_rows" :key=rows.id>
          </single-table-row>
        </tbody>
      </table>
    </div>
  </mytable>
</div>

输出呈现为:

<div id="table_parent">
    <tr>
        <td>2</td>
        <td>Sample 2</td>
    </tr>
    <tr>
        <td>1</td>
        <td>Sample 1</td>
    </tr>
    <tr>
        <td>3</td>
        <td>Sample 3</td>
    </tr>
    <table>
        <thead>
            <tr>
                <th>Id</th>
                <th>Text</th>
            </tr>
        </thead>
        <tbody></tbody>
    </table>
</div>

理想情况下,它应该在<tbody>标签内呈现行组件。
我在这里想念什么?

标签: javascriptvuejs2vue-component

解决方案


您需要使用<tr is="single-table-row"而不是<single-table-row.

https://vuejs.org/v2/guide/components.html#DOM-Template-Parsing-Caveats

这是因为您的模板直接在 HTML 中。浏览器会在 Vue 靠近它之前解析它。某些元素,例如tbody,对它们可以拥有的子元素有限制。任何不允许的元素都将被撕掉。当 Vue 参与进来时,他们已经被转移了。

Vue.component('single-table-row', {
  props: {
    row: {
      type: Object
    }
  },
  template: `
    <tr>
    <td>{{row.id}}</td>
    <td>{{row.text}}</td>
    </tr>
  `
});

Vue.component('mytable', {
  props: {
    tabledata: {
      type: Object
    }
  },
  data: function () {
    return {
      headers: ['Id', 'Text']
    }
  },
  computed: {
    table_rows: function () {
      return this.tabledata.data.rows;
    }
  }
});

var app3 = new Vue({
  el: '#app-3',
  data: {
    mydata: {
      data: {
        rows: [
          {
            id: 1,
            text: 'Sample 1'
          },
          {
            id: 2,
            text: 'Sample 2'
          },
          {
            id: 3,
            text: 'Sample 3'
          }
        ]
      }
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app-3">
  <mytable v-bind:tabledata="mydata" inline-template>
    <div id="table_parent">
      <table>
        <thead>
          <tr>
            <th v-for="header in headers">{{header}}</th>
          </tr>
        </thead>
        <tbody>
          <tr is="single-table-row" :row=rows v-for="rows in table_rows" :key=rows.id>
          </tr>
        </tbody>
      </table>
    </div>
  </mytable>
</div>


推荐阅读