Vue插槽内的BootstrapVue表模板
Posted
技术标签:
【中文标题】Vue插槽内的BootstrapVue表模板【英文标题】:BootstrapVue table-template inside Vue slot 【发布时间】:2018-12-05 00:30:41 【问题描述】:我想为带有自定义数据呈现(模板)的 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>
有没有人做过类似的事情并想出了解决办法?
【问题讨论】:
【参考方案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>
这就像一个魅力!
【讨论】:
【参考方案2】:感谢@nardnob,这是我在.vue
组件中使用的。所有b-table
组件都已加载到我的app.js
文件中。因此缺少导入语句。
首先是TableWrapper.vue
。我添加了Object.assign(this.$attrs, this.$props)
以确保CustomTable
中的任何未定义props
仍将通过组合$attrs
和$props
继续传递到b-table
。
<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>
【讨论】:
【参考方案3】:You can use a component's render function 将 slot 和 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>
【讨论】:
感谢分享!它让我完全陷入困境,试图弄清楚。我也会发布我的.vue
解决方案以供将来参考:)
很高兴它可以提供帮助。我将其发布为我自己的未来参考和其他所有人一样=)以上是关于Vue插槽内的BootstrapVue表模板的主要内容,如果未能解决你的问题,请参考以下文章
如何在 b-table 的 v-slot:cell() 模板中获取项目值 - BootstrapVue
BootstrapVue - 未定义属性或方法“数据”......使用范围插槽时
将 BootstrapVue 与 Vue.Draggable 一起使用?并将项目从列表中删除到 b 表?