BootstrapVue таблица-шаблон внутри слота Vue
Я хочу создать родительский компонент для таблицы начальной загрузки с настраиваемым отображением данных (шаблоны).
Прямо сейчас это выглядит примерно так:
<b-table
:items="result"
:fields="fields"
:current-page="currentPage"
:per-page="perPage">
<template slot="Index" slot-scope="data">
{{ data.index + 1 }}
</template>
<!-- more templates for various columns here -->
</b-table>
<b-pagination
align="center"
:total-rows="result.length"
v-model="currentPage"
:per-page="perPage"
/>
Причина, по которой я хочу обернуть это в компоненте, заключается в том, что я использую этот макет таблицы, включая нумерацию страниц и все ее атрибуты (такие как чередование, границы и т. Д.), Несколько раз.
Единственное, что меняется, это столбцы-шаблоны.
Я знаю, что Vue способ сделать это будет создать слот, как <slot name="x"></slot>
и заполните его <template slot="x">...</template>
, С одной стороны, это будет совпадать с начальной загрузкой template
а с другой стороны, bootstrap-vue, по-видимому, корректно отображает шаблоны только в том случае, если они расположены прямо внутри b-table
,
По сути, я хочу добиться такого компонента:
<b-table>
<slot name="templates"/>
</b-table>
<b-pagination stuff.../>
И используйте его в дочернем компоненте так:
<TemplateTable>
<template slot="templates">
<template slot="Index" slot-scope="data">
{{ data.index + 1 }}
</template>
<!-- more templates -->
</template>
</TableTemplate>
Кто-нибудь сделал что-то подобное и нашел способ решить это?
1 ответ
Просто создайте свой собственный компонент и передайте любые нужные вам реквизиты примерно так:
<template>
<b-table v-bind="$attrs" v-on="$listeners" custom-prop="any">
<slot v-for="(_, name) in $slots" :name="name" :slot="name" />
<template
v-for="(_, name) in $scopedSlots"
:slot="name"
slot-scope="slotData"
><slot :name="name" v-bind="slotData"
/></template>
</b-table>
</template>
<script>
export default {
name: 'AppTable',
}
</script>
<style scoped></style>
это работает как шарм!
Вы можете использовать функцию рендеринга компонента для передачи слотов и scopedSlots другому компоненту (например, b-table
). Но тогда вы не можете использовать шаблон. Чтобы у вас был шаблон (с разбиением на страницы, поиском и т. Д.), Вы можете заключить компонент рендеринга в другой компонент, у которого есть шаблон. Итак, у вас будет custom-table
компонент, который содержит нумерацию страниц и table-wrapper
компонент, а table-wrapper
Компонент будет оказывать b-table
,
Вот очень конкретный пример..
const constItems = [{
index: 0,
isActive: true,
age: 40,
first_name: 'Dickerson',
last_name: 'Macdonald'
},
{
index: 1,
isActive: false,
age: 21,
first_name: 'Larsen',
last_name: 'Shaw'
},
{
index: 2,
isActive: false,
age: 89,
first_name: 'Geneva',
last_name: 'Wilson'
},
{
index: 3,
isActive: true,
age: 38,
first_name: 'Jami',
last_name: 'Carney'
}
];
const bTableProps = {
items: {
type: [Array, Function],
default: undefined
},
fields: {
type: [Object, Array],
default: undefined
}
};
const constFields = [
'index',
'isActive',
'age',
'first_name',
'last_name'
];
Vue.component('table-wrapper', {
props: Object.assign({}, bTableProps),
render(h) {
return h('b-table', {
props: this.$props,
slots: this.$parent.$slots,
scopedSlots: this.$parent.$scopedSlots,
on: {
'row-clicked': (item, index, event) => alert('clicked ' + index)
}
});
}
});
Vue.component('custom-table', {
template: '<div><h3>hello table</h3><table-wrapper :items="items" :fields="fields"></table-wrapper></div>',
props: Object.assign({}, bTableProps)
});
new Vue({
el: "#app",
data: {
items: constItems,
fields: constFields
}
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link href="https://unpkg.com/bootstrap@4.1.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue@2.0.0-rc.11/dist/bootstrap-vue.css" rel="stylesheet" />
<script src="https://unpkg.com/babel-polyfill@6.26.0/dist/polyfill.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.0.0-rc.11/dist/bootstrap-vue.js"></script>
<div id="app">
<custom-table :items="items" :fields="fields">
<template slot="index" slot-scope="data">
{{ data.index + 1 }}
</template>
</custom-table>
<custom-table :items="items" :fields="fields">
<template slot="index" slot-scope="data">
{{ data.index + 2 }}
</template>
</custom-table>
<custom-table :items="items" :fields="fields">
<template slot="index" slot-scope="data">
{{ data.index + 3 }}
</template>
</custom-table>
</div>
Благодаря @nardnob это то, что я использую в своем .vue
составные части. Всеb-table
компоненты уже загружены в мой app.js
файл. Следовательно, отсутствие операторов импорта.
Сначала TableWrapper.vue
. я добавилObject.assign(this.$attrs, this.$props)
чтобы убедиться, что любое неопределенное props
из CustomTable
все равно будет перенесен на b-table
путем объединения $attrs
а также $props
.
<script>
export default {
components: {},
props: [
'items',
'fields'
],
mixins: [],
data: function () {
return {
//
}
},
render(h) {
return h('b-table', {
props: Object.assign(this.$attrs, this.$props),
slots: this.$parent.$slots,
scopedSlots: this.$parent.$scopedSlots,
on: {
// 'row-clicked': (item, index, event) => alert('clicked ' + index)
}
});
},
computed: {
//
},
created() {
//
},
mounted() {
//
},
methods: {
//
},
watch: {
//
}
}
</script>
Тогда CustomTable.vue
:
<template>
<table-wrapper
:items="items"
:fields="fields"
:striped="true"
></table-wrapper>
</template>
<script>
export default {
components: {},
props: [
'fields',
'items',
],
mixins: [],
data: function () {
return {
//
}
},
computed: {
//
},
created() {
//
},
mounted() {
//
},
methods: {
//
},
watch: {
//
}
}
</script>
И наконец:
<custom-table
:fields="[
{
key: 'code',
label: 'Code',
},
{
key: 'title',
label: 'Titel',
},
{
key: 'start_date',
label: 'Start',
},
{
key: 'end_date',
label: 'End',
},
{
key: 'log',
label: 'Log'
}
]"
:items="episodes"
>
<template v-slot:cell(log)="data">
<i class="fa-icon fa-search ml-1 is-hoverable" @click="test"></i>
</template>
</custom-table>