自定义Pagination分页组件
最近在学Vue.js框架,理论知识学得再多,不如自己实践一遍,获得更深的感悟。因此决定封装Element-UI 的Pagination
分页组件
以下代码中的特性使用的是Vue2版本
el-pagination
从官网拷贝代码如下:
<template>
<div class="block">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[100, 200, 300, 400]"
:page-size="100"
layout="total, sizes, prev, pager, next, jumper"
:total="400">
</el-pagination>
</div>
</templete>
<script>
export default {
methods: {
handleSizeChange(val) {
console.log(`每页 ${val} 条`);
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`);
}
},
data() {
return {
currentPage: 1
};
}
}
</script>
size-change: 设置每页的数量,触发handleSizeChange
事件
current-change: 设置第几页,触发handleCurrentChange
事件
其他的字段就不在解释了,比较简单
在不封装的情况下,直接在组件内部使用此代码,修改比较简单:
- page-sizes,page-size,total,currentPage 使用变量而非固定值
- 事件触发时,修改配置,并重新获取表单中的数据来更新表单
封装分页组件
多个页面存在表单的情况,需要复制分页的代码和逻辑,比较麻烦!把具备通用性的分页组件封装起来会更加高效。
创建子组件
创建文件src/components/Pagination/index.vue
<template>
<div class="pagination-container">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="pageSizes"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</div>
</template>
<script>
export default {
name: "MyPagination",
props: { // 申明哪些参数,需要父组件传入进来,同时描述类型和默认值
total: {
require: true,
type: Number
},
pageNum: {
type: Number,
default: 1
},
pageSize: {
type: Number,
default: 20
},
pageSizes: {
type: Array,
default() {
return [10, 20, 30, 50]
}
},
},
data() {
return { // 注意:此处没有设置任何数值
}
},
methods: {
handleSizeChange(val) {
this.$emit('update:pageSize', val) // 此处用来同步`pageSize`给父组件,注意`update:`前缀是固定写法
// `pagination`是一个自定义事件,只要父组件和子组件默契的承接即可。父组件接受到此事件则刷新表单,pagination({pageNum:xxx, pageSize: xxx})
this.$emit("pagination", {pageNum: this.pageNum, pageSize: this.pageSize})
handleCurrentChange(val) {
this.$emit("update:pageNum", val) // 此处用来同步`pageNum`给父组件,注意`update:`前缀是固定写法
this.$emit("pagination", {pageNum: this.pageNum, pageSize: this.pageSize})
}
}
}
</script>
分页组件中,只有pageNum
和pageSize
是用户经常设置,其他变量不变,可由父组件传入。
增加一个自定义pagination
事件的原因,在于父组件能够根据事件,刷新表单数据,非常重要! 比通过监听变量
的方式触发表单更新更加高效。
父组件代码如下:
<template>
<MyPagination :total="total" :pageNum.sync="queryParams.pageNum" :pageSize.sync="queryParams.pageSize" @pagination="getList"/>
</template>
<script>
export default {
data(){
return {
tableData: [],
queryParams: {
pageNum: 1,
pageSize: 10,
num: null
},
total: 20,
}
},
methods: {
getList(data){
console.log("更新表单数据")
}
}
}
<script>
:pageNum.sync
其中:pageNum
是子组件中注册的pageNum
, 同理:pageSize.sync
是子组件注册的pageSize
@pagination
这个事件是必须与子组件中$emit("pagination")
申明的事件保持一致
由于分页数据是常用的组件,则在全局注册
// main.js
import Vue from 'vue'
import Pagination from "@/components/Pagination"
Vue.component('MyPagination', Pagination)
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
知识点
父子组件的通信
父组件在模版中使用子组件,采用:pageSize:sync=pageSize
,:pageSize.sync
表示在子组件中使用一个pageSize
的属性值,由父组件中数据pageSize
设置初始值
子组件通过props:{ pageSize: {type: Number}}
中声明属性,可以通过this.pageSize
进行访问,但是此属性不能直接赋值,但是可以使用this.$emit("update:pageSize", 2)
进行传值。
当然更优雅的方式是给属性使用computed
计算属性来定义一个新变量,此方法不在详细叙述。
自定义事件
子组件发送pagination
事件this.$emit('pagination', data)
给父组件
父组件定义了接收方法@pagination="getList"
总结
组件的封装的套路大体上是一致的,应该还涉及到一些知识点,比如v-model
等,多做小项目,会加深理解,加油!!!