我想为带有自定义数据呈现(模板)的bootstrap-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>
填充它。一方面,这与bootstrap-vue 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>
有人做过这样的事情并想出一种解决办法吗?
答案 0 :(得分:1)
You can use a component's render function将插槽和scopeSlot传递到另一个组件(例如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>
答案 1 :(得分:0)
感谢@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>
答案 2 :(得分:0)
只需构建您的自定义组件并传递任何您需要的自定义道具,即可:
<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>
这就像一种魅力!