我正在使用vue 2.5和库Bootstrap-vue。 我对该库的表组件感兴趣:https://bootstrap-vue.js.org/docs/components/table
但是我想封装该组件,以使用不需要重复的自定义配置来创建自己的组件。这样,我不必每次都管理分页和过滤,并且可以添加其他功能,例如数据导出。
所以我创建了一个表格帮助器组件(目前仅处理分页)
<template>
<div>
<b-table striped hover responsive
:items="items" :fields="fields"
:current-page="currentPage" per-page="10">
<slot></slot>
</b-table>
<b-pagination :total-rows="items.length" per-page="10" v-model="currentPage"></b-pagination>
</div>
</template>
<script>
import bTable from 'bootstrap-vue/es/components/table/table'
import bPagination from 'bootstrap-vue/es/components/pagination/pagination'
export default {
name: "table-helper",
props: ['items', 'fields'],
data() {
return {
currentPage: 1,
}
},
components: {
'b-table': bTable,
'b-pagination': bPagination
}
}
</script>
我想像这样使用我的组件(使用bootstrap-vue插槽的可能性来重新格式化列):
<table-helper :items="users" :fields="fields">
<template slot="fullName" slot-scope="data">
{{data.item.first_name}} {{data.item.last_name}}
</template>
</table-helper>
显然,它不起作用(我得到了表格,但没有格式化的列),因为<template slot="fullName" slot-scope="data">
是指我的自定义组件,而不是b表组件。
所以我想知道一种封装库组件的方法,该组件使用这样的插槽和插槽范围。
谢谢您的帮助。
答案 0 :(得分:0)
要点:
模板与JSX :您可能必须使用JSX来实现它,尤其是对于广告位。
插槽:对于您的情况,父组件的插槽将是b-table
的子VNode,因此将插槽重塑为一个数组并将上下文从父级更改为当前(如果未正确显示 scopedSlot 。),则将它们放入function = h的第三个参数中(或者您可以调用createElement
)。有关详细信息,请检查Vue Guide: Create Element Arguments。
无论如何,请仔细阅读Best Way To Implement HOC,然后您就可以实现目标。
Vue.config.productionTip = false
Vue.component('table-helper', {
render (h) {
const slots = Object.keys(this.$slots)
.reduce((arr, key) => arr.concat(this.$slots[key]), [])
.map(vnode => {
vnode.context = this._self
return vnode
})
const self = this
return h('div', [
h('b-table', {
on: self.$listeners,
props: Object.assign(self.$props, {currentPage: self.currentPage}),
scopedSlots: self.$scopedSlots,
attrs: self.$attrs
},slots),
h('b-pagination', {
props: self.$props,
domProps: {
value: self.currentPage
},
on: {
input: function (event) {
self.currentPage = event
}
}
})
])
},
//mixins: [{bTable.props}, {bPagination.props}],
props: ['items', 'fields', 'perPage','totaRows'],
data() {
return {
currentPage: 1,
}
}
})
new Vue({
el: '#app',
data() {
return {
fields: [ 'first_name', 'last_name', 'age', 'fullName' ],
users: [
{ isActive: true, age: 40, first_name: 'Dickerson', last_name: 'Macdonald' },
{ isActive: false, age: 21, first_name: 'Larsen', last_name: 'Shaw' },
{ isActive: false, age: 89, first_name: 'Geneva', last_name: 'Wilson' },
{ isActive: true, age: 38, first_name: 'Jami', last_name: 'Carney' },
{ isActive: true, age: 40, first_name: 'Dickerson', last_name: 'Macdonald' },
{ isActive: false, age: 21, first_name: 'Larsen', last_name: 'Shaw' },
{ isActive: false, age: 89, first_name: 'Geneva', last_name: 'Wilson' },
{ isActive: true, age: 38, first_name: 'Jami', last_name: 'Carney' },
{ isActive: true, age: 40, first_name: 'Dickerson', last_name: 'Macdonald' },
{ isActive: false, age: 21, first_name: 'Larsen', last_name: 'Shaw' },
{ isActive: false, age: 89, first_name: 'Geneva', last_name: 'Wilson' },
{ isActive: true, age: 38, first_name: 'Jami', last_name: 'Carney' }
]
}
}
})
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<script src="//unpkg.com/babel-polyfill@latest/dist/polyfill.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue/dist/bootstrap-vue.js"></script>
<div id="app">
<table-helper :items="users" :fields="fields" :per-page="10" :total-rows="users.length">
<template slot="fullName" slot-scope="data">
{{data.item.first_name}} {{data.item.last_name}}
</template>
</table-helper>
</div>