我来为你讲解 “Vue.js管理后台table组件封装的方法”的完整攻略。
一、背景介绍
在管理后台开发中,表格展示是必不可少的控件,但是我们往往还需要对表格做各种处理,例如支持多选、排序等等,因此将表格进行封装,可以提高开发效率,简化代码复杂度。
二、封装思路
我们将 Table 的一些常用功能进行封装,例如:
- 支持多选/单选
- 支持数据的增删改查操作
- 支持行样式/列样式的自定义
- 支持排序/筛选功能
具体实现方法有很多,下面我将提供一种比较常见的封装思路。
1. 创建基础 Table 组件
首先,我们需要创建一个基础的 Table 组件,包含了最基本的展示数据功能。在组件中,我们可以通过 props 的方式传入表格的列数据和行数据,然后通过 v-for 指令进行渲染。
<template>
<table>
<thead>
<tr>
<th v-for="column in columns" :key="column.field">{{ column.label }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in rows" :key="index">
<td v-for="column in columns" :key="column.field">{{row[column.field]}}</td>
</tr>
</tbody>
</table>
</template>
<script>
export default {
props: {
columns: {
type: Array,
default: () => []
},
rows: {
type: Array,
default: () => []
}
}
}
</script>
2. 增加多选/单选功能
为了支持多选/单选功能,我们需要添加一个复选框,以及对应的选中状态。我们可以在组件的 data 中添加一个 selectedRows 属性,用于存储当前选中的行数据。然后在表格中添加一个选择列,通过 v-model 双向绑定实现选择状态的控制。
<template>
<table>
<thead>
<tr>
<th>
<input type="checkbox"
v-model="allSelected"
@change="selectAll($event)"/>
</th>
<th v-for="column in columns" :key="column.field">{{ column.label }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in rows" :key="index">
<td>
<input type="checkbox"
v-model="selectedRows"
:value="row"/>
</td>
<td v-for="column in columns" :key="column.field">{{row[column.field]}}</td>
</tr>
</tbody>
</table>
</template>
<script>
export default {
props: {
columns: {
type: Array,
default: () => []
},
rows: {
type: Array,
default: () => []
}
},
data() {
return {
allSelected: false,
selectedRows: []
}
},
methods: {
selectAll(event) {
this.selectedRows = event.target.checked ? this.rows : []
}
}
}
</script>
3. 增加数据的增删改查功能
为了支持数据的增删改查功能,我们需要在 Table 组件中添加一些按钮,用于操作数据。例如,添加按钮、编辑按钮、删除按钮等等。然后我们可以提取一个 Dialog 组件,用于添加和编辑数据,并使用 slot 的方式将表单内容传入,相当于将弹窗的内容进行了封装。在 Dialog 中,我们可以通过 $emit 方式触发表格的 update 和 create 事件,数据更新后再更新表格即可。
<template>
<div>
<button @click="create">添加</button>
<table>
<!-- 表头 -->
<thead>
<tr>
<th>
<input type="checkbox"
v-model="allSelected"
@change="selectAll($event)"/>
</th>
<th v-for="column in columns" :key="column.field">{{ column.label }}</th>
<th>操作</th>
</tr>
</thead>
<!-- 数据 -->
<tbody>
<tr v-for="(row, index) in rows" :key="index">
<td>
<input type="checkbox"
v-model="selectedRows"
:value="row"/>
</td>
<td v-for="column in columns" :key="column.field">{{row[column.field]}}</td>
<td>
<button @click="edit(row)">编辑</button>
<button @click="remove(row)">删除</button>
</td>
</tr>
</tbody>
</table>
<Dialog v-model="dialogVisible"
@update="update"
@create="create">
<!-- 插槽,用于传递弹窗中的表单数据 -->
<slot name="form"></slot>
</Dialog>
</div>
</template>
<script>
import Dialog from '@/components/Dialog.vue'
export default {
components: {
Dialog
},
props: {
columns: {
type: Array,
default: () => []
},
rows: {
type: Array,
default: () => []
}
},
data() {
return {
allSelected: false,
selectedRows: [],
dialogVisible: false,
currentRow: {}
}
},
methods: {
create() {
this.currentRow = {}
this.dialogVisible = true
},
update(row) {
// 更新数据
this.rows = this.rows.map(item => item.id === row.id ? row : item)
},
remove(row) {
// 删除数据
this.rows = this.rows.filter(item => item.id !== row.id)
},
selectAll(event) {
this.selectedRows = event.target.checked ? this.rows : []
},
edit(row) {
// 编辑数据
this.currentRow = {...row}
this.dialogVisible = true
}
}
}
</script>
4. 增加样式的自定义
为了支持样式的自定义,我们可以在 Table 中定义 slot,用于传入行样式和列样式。例如,我们可以在 tr 中添加一个 row-class 的属性,用于设置行的样式名,然后在表格中添加一个名为 row 的 slot,并根据传递的 row 数据设置样式。列样式的自定义也类似。
<template>
<table>
<!-- 表头 -->
<thead>
<tr>
<th>
<input type="checkbox"
v-model="allSelected"
@change="selectAll($event)"/>
</th>
<th v-for="column in columns" :key="column.field">{{ column.label }}</th>
<th>操作</th>
</tr>
</thead>
<!-- 数据 -->
<tbody>
<tr v-for="(row, index) in rows" :key="index"
:class="getRowClass(row)">
<td>
<input type="checkbox"
v-model="selectedRows"
:value="row"/>
</td>
<td v-for="column in columns" :key="column.field"
:class="getColumnClass(row, column.field)">{{row[column.field]}}</td>
<td>
<button @click="edit(row)">编辑</button>
<button @click="remove(row)">删除</button>
</td>
</tr>
</tbody>
<!-- 插槽,用于传递行样式和列样式 -->
<slot name="row" :row="rows"></slot>
<slot name="column"></slot>
</table>
</template>
<script>
import Dialog from '@/components/Dialog.vue'
export default {
components: {
Dialog
},
props: {
columns: {
type: Array,
default: () => []
},
rows: {
type: Array,
default: () => []
}
},
data() {
return {
allSelected: false,
selectedRows: [],
dialogVisible: false,
currentRow: {}
}
},
methods: {
create() {
this.currentRow = {}
this.dialogVisible = true
},
update(row) {
// 更新数据
this.rows = this.rows.map(item => item.id === row.id ? row : item)
},
remove(row) {
// 删除数据
this.rows = this.rows.filter(item => item.id !== row.id)
},
selectAll(event) {
this.selectedRows = event.target.checked ? this.rows : []
},
edit(row) {
// 编辑数据
this.currentRow = {...row}
this.dialogVisible = true
},
// 获取行样式,在插槽中使用
getRowClass(row) {
// todo: 实现根据不同的条件返回不同的 class 名称
return 'row-class'
},
// 获取列样式,在插槽中使用
getColumnClass(row, field) {
// todo: 实现根据不同的条件返回不同的 class 名称
return 'column-class'
}
}
}
</script>
5. 增加排序/筛选功能
为了支持排序/筛选功能,我们可以在表头的列上添加一个排序/筛选图标,然后监听点击事件,通过排序/筛选算法对数据进行操作即可。例如,我们可以在 Table 中定义一个 sortField 和 sortType 属性,用于存储当前的排序字段和排序类型,然后在点击表头列时根据当前的排序状态修改 sortField 和 sortType,最后使用 Array.sort 方法对数据进行排序。
<template>
<table>
<!-- 表头 -->
<thead>
<tr>
<th>
<input type="checkbox"
v-model="allSelected"
@change="selectAll($event)"/>
</th>
<th v-for="column in columns" :key="column.field"
@click="handleSort(column.field)">
{{ column.label }}
<span class="sort-icon"
:class="{
'sort-asc': sortField === column.field && sortType === 'asc',
'sort-desc': sortField === column.field && sortType === 'desc'
}"></span>
</th>
<th>操作</th>
</tr>
</thead>
<!-- 数据 -->
<tbody>
<tr v-for="(row, index) in rows" :key="index"
:class="getRowClass(row)">
<td>
<input type="checkbox"
v-model="selectedRows"
:value="row"/>
</td>
<td v-for="column in columns" :key="column.field"
:class="getColumnClass(row, column.field)">{{row[column.field]}}</td>
<td>
<button @click="edit(row)">编辑</button>
<button @click="remove(row)">删除</button>
</td>
</tr>
</tbody>
<!-- 插槽,用于传递行样式和列样式 -->
<slot name="row" :row="rows"></slot>
<slot name="column"></slot>
</table>
</template>
<script>
import Dialog from '@/components/Dialog.vue'
export default {
components: {
Dialog
},
props: {
columns: {
type: Array,
default: () => []
},
rows: {
type: Array,
default: () => []
}
},
data() {
return {
allSelected: false,
selectedRows: [],
dialogVisible: false,
currentRow: {},
sortField: '',
sortType: ''
}
},
methods: {
create() {
this.currentRow = {}
this.dialogVisible = true
},
update(row) {
// 更新数据
this.rows = this.rows.map(item => item.id === row.id ? row : item)
},
remove(row) {
// 删除数据
this.rows = this.rows.filter(item => item.id !== row.id)
},
selectAll(event) {
this.selectedRows = event.target.checked ? this.rows : []
},
edit(row) {
// 编辑数据
this.currentRow = {...row}
this.dialogVisible = true
},
// 获取行样式,在插槽中使用
getRowClass(row) {
// todo: 实现根据不同的条件返回不同的 class 名称
return 'row-class'
},
// 获取列样式,在插槽中使用
getColumnClass(row, field) {
// todo: 实现根据不同的条件返回不同的 class 名称
return 'column-class'
},
// 排序
sort() {
// 从小到大排序
if (this.sortType === 'asc') {
this.rows.sort((a, b) => a[this.sortField] - b[this.sortField])
}
// 从大到小排序
if (this.sortType === 'desc') {
this.rows.sort((a, b) => b[this.sortField] - a[this.sortField])
}
},
// 点击表头排序
handleSort(field) {
// 默认为从小到大排序
let type = 'asc'
// 如果当前点击的就是排序的列,那么将排序类型翻转
if (this.sortField === field) {
type = this.sortType === 'asc' ? 'desc' : 'asc'
}
// 更新排序状态
this.sortField = field
this.sortType = type
// 对数据进行重新排序
this.sort()
}
}
}
</script>
三、总结
以上就是 Vue.js 管理后台 Table 组件的封装方法。通过封装 Table 组件,我们可以提高开发效率,优化代码结构,降低维护成本。当然,以上示例中的实现方式还有很多需要改进的地方,可以根据需求进行相应的调整和改动。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue.js管理后台table组件封装的方法 - Python技术站