前言
需要具备父子组件通信的知识 不知道的可以看我的笔记了解--里面的第26、27条
- 多页面结构截图
image.png
- 效果 gif 图
Animation47.gif
正文
分页组件源码
- 新建分页
.vue
文件src
->components
->pagination
->index.vue
,编辑index.vue
文件
<template>
<div>
<!-- 分页 -->
<nav aria-label="Page navigation" class="text-center">
<ul class="pagination">
<li @click="previousGo">
<a href="javascript:void(0);" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<li v-for="(page,index) in pages" :key="index" @click="pageGo(page)" :class="{ 'active' : page === pageNumber}">
<a href="javascript:void(0);">{{ page }}</a>
</li>
<li @click="nextGo">
<a href="javascript:void(0);" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</div>
</template>
<script>
// import qs from 'qs' // 解决 axios 数据提交格式与后台不一致的问题 -> name=hehe&age=10
export default {
props: ['parentPageData'], // 父组件数据 别名
name: 'Pagination',
data() {
return {
// 当前页码
pageNumber: null,
// 分页展示数量
pageSize: null,
// 数据总数量
totalRow: null,
// 页码数组
pages: []
}
},
watch: {
// 监听父组件数据变化实时更新数据
parentPageData: {
handler: 'loadPageList',
immediate: true
}
},
methods: {
// 转换数据
transformPageData: function() {
const me = this
const pagePlugin = me.$parent.$data.pagePlugin
// console.log(pagePlugin)
me.pageNumber = pagePlugin.pageNumber
me.pageSize = pagePlugin.pageSize
me.totalRow = pagePlugin.totalRow
},
// 加载页面数据
loadPageList: function() {
// 页码数组
const me = this
me.transformPageData()
let _length = me.pageSize // 每页数量 & 页码列表总长度
let _page = me.pageNumber // 当前页面
let _max = Math.ceil(me.totalRow / _length) // 最多的页码数字
// console.log(_length + ' ' + _page + ' ' + _max)
// 不是首次请求页码操作
// 增加:判断页面长度是否为 页码列表总长度 修复 bug,bug 说明:如果当前搜索成功之后,但是页码数量少于 页码列表总长度 ,比如两页,之后将搜索框内容手动删除,再点击分页会出现请求到的数据已更新为全部,但是分页列表数组 length 还是 2 导致的 bug
if (_page !== 1 && me.pages.length === _length) {
if (_page === me.pages[0]) {
// 当前页码数是数组中的第一个页码
me.pages.pop() // 删除数组中最后一个元素
me.pages.unshift(me.pageNumber - 1) // 向第一个元素前面追加一个元素
return false
} else if (_page === me.pages[me.pages.length - 1] && _page !== _max) {
// 当前页码数是数组中的最后一个页码 且这个值不是总页码的最后一页
me.pages.shift() // 删除数组中第一个元素
me.pages.push(me.pageNumber + 1) // 向末尾增加一个元素
return false
} else if (me.pages.indexOf(_page) > -1) {
// 当前的页码数存在于当前的页码数组中 不会向下重新拼接数组
return false
}
}
// 拼接页码操作
let arr = []
// 如果总页码不足 10 页 循环次数为页码数
if (_max < 10) _length = _max
// 当前页面已经是最后一页 倒数排列
if (_page >= _max) {
while (_length--) {
arr.push(_page--)
}
arr.reverse()
} else {
while (_length--) {
arr.push(_page++)
}
}
me.pages = arr
},
// 分页点击
pageGo: function(number) {
const me = this
// 点击的是当前页码 return
if (me.pageNumber === number) return
me.$parent.$data.pagePostData.page_number = number
me.pageNumber = number
// 调用父组件方法
me.$emit('updatePageData')
// me.transformPageData()
// me.loadPageList()
},
// 上一页点击
previousGo: function() {
const me = this
// 当前页码为 1 return
if (me.pageNumber === 1) {
return false
} else {
me.pageGo(me.pageNumber - 1)
}
},
// 下一页点击
nextGo: function() {
const me = this
// 当前页码为 最后一页 return
if (me.pageNumber * me.pageSize >= me.totalRow) {
return false
} else {
me.pageGo(me.pageNumber + 1)
}
}
}
}
</script>
<style lang="less">
</style>
- 父组件相应的使用示例,多余的源码已删除
<template>
<div class="container row">
<div class="col-sm-10">
<div class="row">
<form class="navbar-form navbar-left col-sm-5" @submit.prevent="searchForm">
<div class="form-group">
<input type="text" class="form-control" placeholder="搜索" v-model="pagePostData.seach_name_phone">
</div>
<button type="submit" class="btn btn-default">搜索</button>
</form>
<div class="col-sm-7 text-right mtb-8">
<button type="button" class="btn btn-primary" data-toggle="tooltip" data-placement="top" title="下载示例文件及相关操作">下载示例</button>
<button type="button" class="btn btn-primary" data-toggle="tooltip" data-placement="top" title="">导出</button>
<button type="button" class="btn btn-primary" data-toggle="tooltip" data-placement="top" title="" @click="openFilePopup">导入</button>
<a href="addstaff.html" class="btn btn-link">新建成员</a>
<a href="quitlist.html" class="btn btn-link">离职员工</a>
</div>
</div>
<table class="table table-bordered">
<caption>成员列表</caption>
<thead>
<tr>
<th> </th>
<th>姓名</th>
<th>部门</th>
<th>职位</th>
<th>电话</th>
<th>套餐</th>
<th>授信额度</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(people,index) in pageGetData" :key="people.id">
<td>
<div class="custom-control custom-checkbox">
<input class="form-check-input" type="checkbox" :id="'inlineCheckbox' + index">
</div>
</td>
<td>{{ people.name }}</td>
<td>{{ people.department }}</td>
<td>{{ people.position }}</td>
<td>{{ people.phone_number }}</td>
<td>{{ people.package_code }}</td>
<td>{{ people.balance }}</td>
<td>{{ people.IS_USED }}</td>
<td>
<span>修改</span>
<span>禁用</span>
<span>移动</span>
<span role="button" @click="leaveGo" :data-number="people.phone_number">离职</span>
<span>详情</span>
</td>
</tr>
</tbody>
</table>
<div class="data-none" v-show="pageGetData.length === 0">暂无数据</div>
<!-- 分页 -->
<pagination @updatePageData="loadPageData" :parentPageData="pageGetData" v-show="pageGetData.length > 0"></pagination>
</div>
<!-- 弹窗 -->
<msg-modal :modal-msg="modalMsg"></msg-modal>
</div>
</template>
<script>
import qs from 'qs' // 解决 axios 数据提交格式与后台不一致的问题 -> name=hehe&age=10
import MsgModal from '@/components/msgmodal'
import Pagination from '@/components/pagination'
export default {
name: 'App',
components: { MsgModal, Pagination },
data() {
return {
// 弹窗信息 在执行操作时使用
modalMsg: '',
// 信息提交接口
pagePostAPI: '/jjhServerApi/ab/getAbByCondition',
// 信息提交数据
pagePostData: {
/**
* page_number 分页页数 不填默认为1
* seach_name_phone 手机号或姓名 非必填 模糊查询传的条件
*/
page_number: '',
seach_name_phone: ''
},
// 页面数据
pageGetData: [],
// 分页组件参数
pagePlugin: {
// 当前页码
pageNumber: '',
// 分页展示数量
pageSize: '',
// 数据总数量
totalRow: ''
}
}
},
mounted() {
const me = this
// 初始化页面数据
me.loadPageData()
},
methods: {
// 加载页面所需的数据
loadPageData: function() {
const me = this
// console.log(qs.stringify(me.pagePostData))
me.axios
.post(me.pagePostAPI, qs.stringify(me.pagePostData))
.then(response => {
// console.log(response)
const getData = response.data
if (getData.code === 0) {
me.pageGetData = getData.result.list
me.pagePostData.page_number = getData.result.pageNumber
// 分页数据转换
me.pagePlugin.pageNumber = getData.result.pageNumber
me.pagePlugin.pageSize = getData.result.pageSize
me.pagePlugin.totalRow = getData.result.totalRow
} else {
me.openAlertModel(getData.info)
}
})
.catch(error => {
console.log(error)
me.openAlertModel('请求服务器失败了,请稍后重试!')
})
},
// 打开弹窗
openAlertModel: function(message) {
const me = this
me.modalMsg = message
$('#myModal').modal('show')
},
// 搜索表单提交
searchForm: function() {
const me = this
// 页码重置为 1
me.pagePlugin.pageNumber = me.pagePostData.page_number = 1
me.loadPageData()
}
}
}
</script>
<style lang="less">
</style>
-
axios
挂载是在相应的js
文件中
import Vue from 'vue'
import axios from 'axios'
Vue.prototype.axios = axios
总结
刚开始觉得还是蛮简单的,后来发现最早时候写的
bug
很多
- 需要注意的地方(
bug
产生的原因):- 搜索后要将 "页码重置为 1"
- "如果当前搜索成功之后,但是页码数量少于 页码列表总长度 ,比如两页,之后将搜索框内容手动删除,再点击分页会出现请求到的数据已更新为全部,但是分页列表数组 length 还是 2 导致的
bug
"
网友评论