В этой статье мы рассмотрим, как создать гибкий и переиспользуемый компонент таблицы в Vue. Особенность этого подхода заключается в том, что колонки и их слоты для кастомизации данных описываются внутри компонента колонки (MyTableColumn
), что делает таблицу более декларативной и удобной для использования.
Что мы будем создавать?
Мы создадим два компонента:
MyTable
— компонент таблицы, который отвечает за рендеринг данных и колонок.MyTableColumn
— компонент колонки, который описывает колонку и предоставляет слот для кастомизации отображения данных.
Шаг 1: Компонент таблицы (MyTable.vue
)
Компонент MyTable
отвечает за рендеринг таблицы. Он собирает колонки из вложенных компонентов MyTableColumn
и использует слоты для кастомизации отображения данных.
<template>
<div>
<slot /> <!-- добавим слот чтобы таблица могла принимать колонки -->
<table>
<thead>
<tr>
<!-- Рендерим заголовки колонок -->
<th v-for="column in columns" :key="column.prop">
{{ column.label }}
</th>
</tr>
</thead>
<tbody>
<!-- Рендерим строки таблицы -->
<tr v-for="(row, rowIndex) in data" :key="rowIndex">
<!-- Рендерим ячейки таблицы -->
<td v-for="column in columns" :key="column.prop">
<!-- Используем слот для рендеринга содержимого ячейки -->
<component :is="column.slot" v-if="column.slot" :row="row" />
<template v-else>
{{ row[column.prop] }}
<!-- Значение по умолчанию, если слот не переопределен -->
</template>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
props: {
data: {
type: Array,
required: true,
},
},
data() {
return {
columns: [], // Колонки будут собираться из вложенных компонентов MyTableColumn
}
},
methods: {
// Метод для добавления колонки
addColumn(column) {
this.columns.push(column)
},
},
provide() {
// Передаем метод addColumn в дочерние компоненты через provide/inject
return {
addColumn: this.addColumn,
}
},
}
</script>
<style scoped>
table {
width: 100%;
border-collapse: collapse;
}
th,
td {
border: 1px solid #ddd;
padding: 8px;
}
th {
background-color: #f4f4f4;
}
</style>
Шаг 2: Компонент колонки (MyTableColumn.vue
)
Компонент MyTableColumn
описывает колонку и предоставляет слот для кастомизации отображения данных. Он передает информацию о колонке и слоте в таблицу через метод addColumn
.
<template>
<!-- Этот компонент не рендерит ничего самостоятельно,
он только передает данные в родительский компонент таблицы -->
</template>
<script>
export default {
props: {
prop: {
type: String,
required: true,
},
label: {
type: String,
required: true,
},
},
inject: ['addColumn'], // Получаем метод addColumn из родительского компонента
data() {
return {
slot: null, // Слот для кастомизации отображения данных
};
},
created() {
// При создании компонента передаем колонку в таблицу
this.addColumn({
prop: this.prop,
label: this.label,
slot: this.slot, // Передаем слот в таблицу
});
},
// Метод для регистрации слота
renderSlot(slot) {
this.slot = slot;
},
};
</script>
Шаг 3: Использование в родительском компоненте
Теперь вы можете использовать компоненты MyTable
и MyTableColumn
в родительском компоненте. Слоты для кастомизации данных описываются внутри компонента колонки.
<template>
<div>
<MyTable :data="tableData">
<!-- Колонка "name" с кастомным слотом -->
<MyTableColumn prop="name" label="Имя">
<template v-slot="{ row }">
<strong>{{ row.name }}</strong>
</template>
</MyTableColumn>
<!-- Колонка "age" с кастомным слотом -->
<MyTableColumn prop="age" label="Возраст">
<template v-slot="{ row }">
<span style="color: blue;">{{ row.age }}</span>
</template>
</MyTableColumn>
</MyTable>
</div>
</template>
<script>
import MyTable from './MyTable.vue';
import MyTableColumn from './MyTableColumn.vue';
export default {
components: {
MyTable,
MyTableColumn,
},
data() {
return {
// Данные для таблицы
tableData: [
{ name: 'Иван', age: 25 },
{ name: 'Мария', age: 30 },
{ name: 'Петр', age: 28 },
],
};
},
};
</script>
Как это работает?
- Компонент
MyTableColumn
:- Описывает колонку (свойства
prop
иlabel
). - Принимает слот для кастомизации отображения данных.
- Передает колонку и слот в таблицу через метод
addColumn
.
- Описывает колонку (свойства
- Компонент
MyTable
:- Собирает колонки и их слоты из вложенных компонентов
MyTableColumn
. - Рендерит таблицу, используя переданные колонки и данные.
- Если слот для колонки переопределен, рендерит его. В противном случае отображает значение по умолчанию.
- Собирает колонки и их слоты из вложенных компонентов
- Родительский компонент:
- Определяет данные для таблицы.
- Описывает колонки с помощью вложенных компонентов
MyTableColumn
. - Переопределяет слоты для кастомизации отображения данных внутри компонента колонки.
Преимущества подхода
- Декларативность: Колонки и их слоты описываются внутри компонента колонки, что делает код более читаемым и понятным.
- Гибкость: Вы можете легко кастомизировать отображение данных в ячейках таблицы.
- Переиспользуемость: Компоненты
MyTable
иMyTableColumn
можно использовать в любом проекте.
Итог
Мы создали гибкий и переиспользуемый компонент таблицы в Vue, где колонки и их слоты описываются внутри компонента колонки. Этот подход делает таблицу более декларативной и удобной для использования. Теперь вы можете легко создавать таблицы с кастомизируемыми ячейками в своих проектах! 🚀
Надеюсь, эта статья была полезной! Если у вас есть вопросы или предложения, оставляйте их в комментариях. 😊
Добавить комментарий