Vue3新拟态组件库开发流程之table组件源码分析攻略
1. 前言
Vue3作为一款优秀的前端框架,不断地为前端开发者带来更加方便和高效的开发模式。其中,拟态风格越来越受到大家的关注,为此,我们今天就来学习一下Vue3新拟态组件库开发流程中的table组件源码分析。
2. 源码分析
2.1. 源文件结构
table组件的源码位于/src/components/table
目录下,相关文件和目录如下:
- table/
- index.js
- table.vue
- table-cell.vue
- table-header.vue
- table-row.vue
源文件结构非常清晰,其中index.js
是对外的入口文件,table.vue
是table组件的主体代码。
2.2. 主体代码分析
首先,我们先看一下table.vue
的代码。
<template>
<table>
<thead>
<tr>
<TableHeader
v-for="(column, key) in columns"
:key="key"
:column="column"
@sortChange="handleSortChange"
/>
</tr>
</thead>
<tbody>
<TableRow
v-for="(row, rowIndex) in rows"
:key="rowIndex"
:row="row"
:columns="columns"
/>
</tbody>
</table>
</template>
<script>
import TableHeader from './table-header.vue'
import TableRow from './table-row.vue'
export default {
name: 'VTable',
components: {
TableHeader,
TableRow
},
props: {
columns: {
type: Array
},
rows: {
type: Array
},
sortColumn: {
type: String,
default: ''
},
sortOrder: {
type: String,
default: 'ascending'
}
},
methods: {
handleSortChange(column) {
this.$emit('sort-change', column)
}
}
}
</script>
可以看到,table.vue
主体代码非常简单,只包含一个<table>
标签,其中含有两个子组件TableHeader
和TableRow
,还有几个props和一个监听事件。我们可以针对这几个部分做一个具体分析。
2.2.1. TableHeader部分
接下来我们看一下TableHeader
组件的代码,它负责将传入的列信息展示在表格上部。TableHeader
组件的代码如下:
<template>
<th>
<slot>{{ column.label }}</slot>
<span v-if="column.sortable" class="sort-icon" :class="{ active: isSorted(column) }">
<svg viewBox="0 0 24 24">
<path
d="M7.41 8.59L6 7.17V21a1 1 0 0 0 2 0V7.17l-1.41 1.42A1 1 0 0 0 6 9a1 1 0 0 0 .71.29 1 1 0 0 0 .7-.29l2.58-2.59a1 1 0 0 0 0-1.41 1 1 0 0 0-1.41 0z"
/>
</svg>
</span>
</th>
</template>
<script>
export default {
name: 'TableHeader',
props: {
column: {
type: Object
}
},
methods: {
isSorted(column) {
return column.prop === this.sortColumn
},
handleClick() {
this.$emit('sortChange', this.column.prop)
}
}
}
</script>
主要由一个<th>
标签组成,标签内部包含列名称column.label
和排序图标。排序图标的显示受到列是否可排序以及当前列是否是排序列的影响。
2.2.2. TableRow部分
接下来我们看一下TableRow
组件的代码,它负责将传入的行信息展示在表格上。TableRow
组件的代码如下:
<template>
<tr>
<TableColumn
v-for="(column, key) in columns"
:key="key"
:column="column"
:row="row"
/>
</tr>
</template>
<script>
import TableColumn from './table-column.vue'
export default {
name: 'TableRow',
components: {
TableColumn
},
props: {
columns: {
type: Array
},
row: {
type: Object
}
}
}
</script>
TableRow
包含多个<TableColumn>
组件,对于每一列信息,它都会将它传入到TableColumn
组件内部去渲染,这里使用了v-for
指令来遍历所有列信息并渲染。TableColumn
组件是一个公共组件,我们将在下一个小节进行讲解。
2.2.3. TableColumn部分
最后我们看一下TableColumn
组件的代码,它负责将传入的数据信息展示在表格上。TableColumn
组件的代码如下:
<template>
<td>
<slot>{{ row[column.prop] }}</slot>
</td>
</template>
<script>
export default {
name: 'TableColumn',
props: {
column: {
type: Object
},
row: {
type: Object
}
}
}
</script>
我们看到,TableColumn
组件仅仅只包含一个<td>
标签,同时它也使用了插槽来动态获取每一行的指定列中的值并进行渲染。这里我们对组件的重利用达到了最大的优化。
3. 示例说明
我们该如何使用这个table组件呢?下面我们来举两个简单的示例说明。
3.1. 基本用法
<template>
<div>
<VTable
:columns="columns"
:rows="rows"
@sort-change="sortChangeHandler"
:sortColumn="sortColumn"
:sortOrder="sortOrder"
/>
</div>
</template>
<script>
import VTable from '@/components/table/index.js'
export default {
name: 'example',
components: {
VTable
},
data() {
return {
columns: [
{ label: '姓名', prop: 'name', sortable: true },
{ label: '年龄', prop: 'age', sortable: true },
{ label: '性别', prop: 'gender' }
],
rows: [
{ name: '小明', age: 18, gender: 1 },
{ name: '小红', age: 16, gender: 0 },
{ name: '小李', age: 20, gender: 1 },
{ name: '小白', age: 18, gender: 0 },
{ name: '小黄', age: 19, gender: 1 }
],
sortColumn: '',
sortOrder: 'ascending'
}
},
methods: {
sortChangeHandler(column) {
if (column === this.sortColumn) {
this.sortOrder = this.sortOrder === 'ascending' ? 'descending' : 'ascending'
} else {
this.sortColumn = column
this.sortOrder = 'ascending'
}
this.sortRows()
},
sortRows() {
this.rows.sort((row1, row2) => {
let ascending = this.sortOrder === 'ascending' ? 1 : -1
let descending = -ascending
if (row1[this.sortColumn] > row2[this.sortColumn]) {
return ascending
} else if (row1[this.sortColumn] < row2[this.sortColumn]) {
return descending
} else {
return 0
}
})
}
}
}
</script>
以上代码实现了一个简单的表格展示功能,其中columns
和rows
是table组件的props,分别对应表格的列信息和行信息。如果某一列可以排序,对应的column
对象中的sortable
值为true
,并且用户可以点击表头中的排序图标进行升序或降序排列。sortColumn
和sortOrder
分别表示当前排序的列和顺序。
3.2. 带分页功能
<template>
<div>
<div class="table-pagination">
<el-pagination
v-model="currentPage"
:total="rows.length"
:page-size="pageSize"
:current-page.sync="currentPage"
:prev-text="'上一页'"
:next-text="'下一页'"
:layout="'prev, pager, next'"
/>
</div>
<VTable
:columns="columns"
:rows="currentPageRows"
@sort-change="sortChangeHandler"
:sortColumn="sortColumn"
:sortOrder="sortOrder"
/>
</div>
</template>
<script>
import VTable from '@/components/table/index.js'
import { ElPagination } from 'element-plus'
export default {
name: 'example',
components: {
VTable,
ElPagination
},
data() {
return {
columns: [
{ label: '姓名', prop: 'name', sortable: true },
{ label: '年龄', prop: 'age', sortable: true },
{ label: '性别', prop: 'gender' }
],
rows: [
{ name: '小明', age: 18, gender: 1 },
{ name: '小红', age: 16, gender: 0 },
{ name: '小李', age: 20, gender: 1 },
{ name: '小白', age: 18, gender: 0 },
{ name: '小黄', age: 19, gender: 1 }
],
sortColumn: '',
sortOrder: 'ascending',
currentPage: 1,
pageSize: 3
}
},
computed: {
currentPageRows() {
let start = (this.currentPage - 1) * this.pageSize
let end = start + this.pageSize
return this.rows.slice(start, end)
}
},
methods: {
sortChangeHandler(column) {
if (column === this.sortColumn) {
this.sortOrder = this.sortOrder === 'ascending' ? 'descending' : 'ascending'
} else {
this.sortColumn = column
this.sortOrder = 'ascending'
}
this.sortRows()
},
sortRows() {
this.rows.sort((row1, row2) => {
let ascending = this.sortOrder === 'ascending' ? 1 : -1
let descending = -ascending
if (row1[this.sortColumn] > row2[this.sortColumn]) {
return ascending
} else if (row1[this.sortColumn] < row2[this.sortColumn]) {
return descending
} else {
return 0
}
})
}
}
}
</script>
以上代码在示例1的基础上加入了分页功能,使用了Element Plus的分页组件。其中,计算属性currentPageRows
根据当前页码和每页显示的数量计算出当前页需要展示的数据行,然后传入到VTable
组件中进行渲染。如果用户点击了分页器上的上一页或下一页按钮,currentPage
会得到更新,计算属性currentPageRows
也会随之更新,自动渲染出新的表格。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue3新拟态组件库开发流程之table组件源码分析 - Python技术站