从 v1.15.2 开始,Bootstrap Table 增加了 Bootstrap Table Vue 组件的支持。
我们可以这样使用 formatter
和 events
这两个列属性来实现对列的自定义显示和事件监听:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
<template>
<BootstrapTable
:columns="columns"
:data="data"
:options="options"
/>
</template>
<script>
import BootstrapTable from 'bootstrap-table/dist/bootstrap-table-vue.esm.js'
export default {
components: {
BootstrapTable
},
data () {
return {
columns: [
{
title: 'Item ID',
field: 'id'
},
{
field: 'name',
title: 'Item Name'
},
{
field: 'price',
title: 'Item Price'
},
{
field: 'actions',
title: 'Actions',
formatter: () => {
return '<button class="btn btn-secondary">Click</button>'
},
events: {
'click .btn': (e, value, row) => {
this.clickRow(row)
}
}
}
],
data: [
{
id: 1,
name: 'Item 1',
price: '$1'
}
],
options: {
search: true,
showColumns: true
}
}
},
methods: {
clickRow (row) {
alert(JSON.stringify(row))
}
}
}
</script>
|
这里有一个在线例子:https://live.bootstrap-table.com/code/wenzhixin/440
可以看到,当我们点击按钮的时候调用了 clickRow
方法,不过我们这里使用的是 jQuery
的事件绑定方法。
使用 vue
的话,你可能会想我是否可以使用 vue
的事件进行绑定呢?
如:
1
2
3
|
formatter: (value, row) => {
return '<button class="btn btn-secondary" @click="clickRow(row)">Click</button>'
}
|
答案是不行,因为这里并不会处理 vue
的事件。
另外我们可能会用到 vue
的 UI 组件,例如 BootstrapVue
,那么你可能会想,这里的 formatter
可否使用 vue
组件呢?
如:
1
2
3
|
formatter: (value, row) => {
return '<b-button @click="clickRow(row)">Click</b-button>'
}
|
当然,这样也是不支持的。那应该怎么办呢?
针对这两个问题,我进行了深入了研究和试验。幸运的是,找到了可行的方案。
技术原理主要是先将 vue
组件保存到一个自定义变量中,然后返回一个只包含 class
的简单 div
,在表格渲染完成之后我们再对其进行转换渲染为对应的 vue
组件。
我们增加了一个方法:
1
2
3
4
5
6
7
8
9
|
vueFormatter (obj) {
const key = `_vue_formatter_${this.vueFormatters.length}`
this.vueFormatters.push({
el: `.${key}`,
name: key,
...obj
})
return `<div class="${key}"/>`
}
|
可以看到我们使用 vueFormatters
这个变量用于保存所有列的 vue
组件信息。
我们知道表格渲染完成的事件为 onPostBody
,我们对其进行监听并对保存的 vue
组件信息进行渲染:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
vueFormatterPostBody () {
if (!this.vueFormatters.length) {
return
}
for (let i = this.vueFormatters.length - 1; i >= 0; i--) {
const formatter = this.vueFormatters[i]
if (document.getElementsByClassName(formatter.name)) {
new Vue(formatter)
this.vueFormatters.splice(i, 1)
}
}
}
|
考虑到会经常复用到,我们创建一个 mixins/table.js
文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
import Vue from 'vue/dist/vue.esm.js'
export default {
data () {
return {
vueFormatters: []
}
},
methods: {
vueFormatter (obj) {
const key = `_vue_formatter_${this.vueFormatters.length}`
this.vueFormatters.push({
el: `.${key}`,
name: key,
...obj
})
return `<div class="${key}"/>`
},
vueFormatterPostBody () {
if (!this.vueFormatters.length) {
return
}
for (let i = this.vueFormatters.length - 1; i >= 0; i--) {
const formatter = this.vueFormatters[i]
if (document.getElementsByClassName(formatter.name)) {
new Vue(formatter)
this.vueFormatters.splice(i, 1)
}
}
}
}
}
|
如何使用:
1
2
3
4
5
6
7
8
9
|
formatter: (value, row) => {
return this.vueFormatter({
template: '<b-button @click="clickRow(row)">Click</b-button>',
data: { row },
methods: {
clickRow: this.clickRow
}
})
}
|
1
2
3
4
5
6
7
|
<BootstrapTable
ref="table"
:columns="columns"
:data="data"
:options="options"
@onPostBody="vueFormatterPostBody"
/>
|
在线例子:https://live.bootstrap-table.com/code/wenzhixin/441
需要注意的是:
由于 new Vue({ template })
需要 full
版本,假如在 webpack 中使用的话,需要修改所有的 vue
的导入:
1
|
import Vue from 'vue/dist/vue.esm.js'
|
或者我们可以设置 Vue 导入的别名:
1
2
3
4
5
|
resolve: {
alias: {
vue$: 'vue/dist/vue.esm.js'
}
}
|
源码:https://github.com/wenzhixin/bootstrap-table-examples/tree/develop/vue-starter
最后,希望这篇文章可以帮到你。