如何制作表行中某些(但不是全部)表单元格的Vue.js组件?

时间:2018-10-29 22:15:03

标签: html templates vue.js html-table

我有一些相关的表列和相邻的表列,希望将它们组合在同一组件中。但是Vue.js模板系统有此限制,即<template>中只能直接包含一个标签。通常,这种无意义的包装器是<div>。但是我可以在表格中使用什么?

我可以为此滥用<span>之类的标签,但是后果不可接受。同一列中的单元格的大小不同,并且表格边框不会折叠。是否有一种方法可以使包装器标签在理想情况下根本不显示在HTML中,或者至少与<div>一样中性?

表格行:

<template>
    <tr v-for="thing in things">
        <td>{{thing.name}}</td>
        <size-component :size="thing.size"></size-component>
        <time-component :time="thing.time"></time-component>
    </tr>
</template>

大小列:

<template>
    <wrap>
        <td>{{size.x}}</td>
        <td>{{size.y}}</td>
        <td>{{size.z}}</td>
    </wrap>
</template>

时间列:

<template>
    <wrap>
        <td>{{time.h}}</td>
        <td>{{time.m}}</td>
        <td>{{time.s}}</td>
    </wrap>
</template>

编辑:

对我而言,这可以归结为一个问题,即没有标签可以将<td>中的<tr> s分组(例如<tr>可以在<table>中以多个{{ 1}}标签)。比较Is there a tag for grouping "td" or "th" tags? 语义<tbody>是用于此目的的,但这无济于事。

对我来说,使用vue-fragment是正确的解决方案:

<colgroup>

2 个答案:

答案 0 :(得分:4)

您是对的,这是Vue的局限性,与the diffing algorithm有关。但是,您可以使用功能组件来呈现多个根元素。

<script>
export default {
  functional: true,
  props: {
    size: {
      type: Object,
      default: () => ({
        x: 1,
        y: 2,
        z: 3
      })
    }
  },
  render: (createElement, context) => [
    createElement('td', context.props.size.x),
    createElement('td', context.props.size.y),
    createElement('td', context.props.size.z)
  ]
}
</script>

另一种选择是使用插件vue-fragments

答案 1 :(得分:1)

要将计算结果添加到@Andreas解决方案中,可以引用父属性。

演示CodeSandbox

功能组件

export default {
  functional: true,
  props: {
    size: {
      type: Object,
      default: () => ({
        x: 1,
        y: 2,
        z: 3
      })
    }
  },
  render: (createElement, context) => [
    createElement("td", context.props.size.x),
    createElement("td", context.props.size.y),
    createElement("td", context.props.size.z),
    createElement("td", context.parent.volume(context.props.size))
  ]
};

父级组件

export default {
  components: {
    SizeComponent
  },
  data() {
    return {
      things: [
        {
          name: 'aName',
          size: { x: 1, y: 2, z: 3 }
        }
      ]
    };
  },
  mounted() {
    // test it is reactive
    setTimeout(()=> { this.things[0].size.x = 2 }, 3000) 
  },
  computed: {
    volume() {
      return (size) => size.x * size.y * size.z;
    }
  },
}