Как сделать компонент Vue.js некоторых (но не всех) ячеек таблицы в строке таблицы? - PullRequest
0 голосов
/ 30 октября 2018

У меня есть несколько связанных и соседних столбцов таблицы, которые я хотел бы сгруппировать в одном компоненте. Но система шаблонов 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>

Edit:

Для меня это сводится к тому, что в группе <td> s нет тега для группы *1023* s (например, <tr> s можно сгруппировать в <table> с несколькими тегами <tbody>). Сравните Есть ли тег для группировки тегов "td" или "th"? Семантически <colgroup> предназначен для этой цели, но это не помогает.

Для меня использование vue-фрагмента оказалось верным решением:

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

<script>
    import { Fragment } from 'vue-fragment';

    export default {
        computed: {
            volume() { return this.size.x * this.size.y * this.size.z },
        },
        components: { Fragment },
        props: ['size']
    }
</script>

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

Чтобы добавить вычисленное в решение @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;
    }
  },
}
0 голосов
/ 30 октября 2018

Вы правы, это ограничение для Vue и имеет какое-то отношение к алгоритму дифференцирования . Однако вы можете использовать функциональный компонент для рендеринга нескольких корневых элементов.

<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-фрагменты

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...