上一节
前面我们做完了分页器的基本功能,现在就做一下与父组件的交互
与父组件传递信息
当我们组件中的页码发生变化时可能需要通知父组件,比如父组件显示的第一页的数据,我们分页组件的myCurrentPage变成了2就是要获取第二页的数据,这时父组件就要重新获取数据。使用一个自定义事件,在上一节的setCurrentPage函授里面this.myCurrentPage = page;操作之后加上一个
this.$emit("currentChange", page);
用法就是上节里面的
<Pagination
:currentPage="xxx"
:total="xxx"
:pageSize="xxx"
:showPageNo="xxx"
@currentChange="xxxxxx"
></Pagination>
父组件与分页组件传递信息
还有一种可能性,父组件的数据发生变化了,比如父组件通过props传递给子组件的currentPage,在初始化的时候才会拿到,后面再修改之后,data中的myCurrentPage: this.currentPage这条数据就不会发生更新,所以当父组件的这个值发生改变之后就要通知子组件。要做一个复用性较高的组件,我觉的不应该是让父组件主动发信息给组件,而是让子组件自己去监听这条数,所以在子组件中添加watch监听,父组件的变了,分页组件就能监听到,立刻更新data数据
watch: {
/**
* 监视父组件传来的页码。同步更新页码
*/
currentPage(value) {
this.myCurrentPage = value;
},
},
优化
我们在做动态渲染按钮的时候,同时使用了v-if和v-for,编辑器可能会给你报错,不会影响程序的运行,但是这两者放在一起使用效率非常低
<button
v-for="item in startEnd.end"
v-if="item >= startEnd.start"
:key="item"
:class="{ active: item === myCurrentPage }"
>
{{ item }}
</button>
优化的方法很简单,在数据渲染之前先对数据进行筛选,在分页组件中再定义一个计算属性startEndArr,将start到end之间的数据筛选出来,在遍历的时候直接从start开始遍历,返回数组arr
computed: {
startEnd() {
// .........
return { start, end };
},
startEndArr(){
const arr = []
const {start, end} = this.startEnd
for(let page = start; page <= end; page++){
arr.push(page)
}
return arr
}
},
然后直接循环arr即可
<button
v-for="item in startEndArr"
:key="item"
:class="{ active: item === myCurrentPage }"
@click="setCurrentPage(item)"
>
{{ item }}
</button>
完整的分页组件
<template>
<div class="pageination">
<!-- 当当前页是1的时候,禁用 -->
<button
:disabled="myCurrentPage === 1"
:class="{ disabled: myCurrentPage === 1 }"
@click="setCurrentPage(myCurrentPage - 1)"
>
上一页
</button>
<button v-if="startEnd.start > 1" @click="setCurrentPage(1)">1</button>
<button class="disabled" v-if="startEnd.start > 2">...</button>
<button
v-for="item in startEndArr"
:key="item"
:class="{ active: item === myCurrentPage }"
@click="setCurrentPage(item)"
>
{{ item }}
</button>
<button class="disabled" v-if="startEnd.end < totalPage - 1">...</button>
<button v-if="startEnd.end < totalPage" @click="setCurrentPage(totalPage)">
{{ totalPage }}
</button>
<button
:disabled="myCurrentPage === totalPage"
:class="{ disabled: myCurrentPage === totalPage }"
@click="setCurrentPage(myCurrentPage + 1)"
>
下一页
</button>
<button class="disabled">共 {{ total }} 条</button>
</div>
</template>
<script>
export default {
name: "Pageination",
props: {
currentPage: {
type: Number,
default: 1,
},
total: {
type: Number,
default: 0,
},
pageSize: {
type: Number,
default: 10,
},
showPageNo: {
type: Number,
default: 5,
validator: function (value) {
return value % 2 === 1;
},
},
},
data() {
return {
myCurrentPage: this.currentPage,
};
},
computed: {
totalPage() {
const { total, pageSize } = this;
return Math.ceil(total / pageSize);
},
startEnd() {
const { myCurrentPage, showPageNo, totalPage } = this;
let start, end;
start = myCurrentPage - Math.floor(showPageNo / 2);
if (start < 1) {
start = 1;
}
end = start + showPageNo - 1;
if (end > totalPage) {
// 修改end为totalPage
end = totalPage;
// reset start
start = end - showPageNo + 1;
if (start < 1) {
start = 1;
}
}
return { start, end };
},
startEndArr(){
const arr = []
const {start, end} = this.startEnd
for(let page = start; page <= end; page++){
arr.push(page)
}
return arr
}
},
methods: {
// 切换页码
setCurrentPage(page) {
// 如果页码没有改变,依然点击了,直接return
if (page === this.myCurrentPage) return;
this.myCurrentPage = page;
// 分发自定义事件,告诉父组件
this.$emit("currentChange", page);
},
},
watch: {
/**
* 监视父组件传来的页码。同步更新页码
*/
currentPage(value) {
this.myCurrentPage = value;
},
},
};
</script>
<style lang="less" scoped>
.pageination {
button {
margin: 0 5px;
background-color: #f4f4f5;
color: #606266;
outline: none;
border-radius: 2px;
pad: 0 4px;
vertical-align: top;
display: inline-block;
font-size: 13px;
min-width: 35.5px;
height: 28px;
line-height: 28px;
cursor: pointer;
box-sizing: border-box;
text-align: center;
border: 0;
&.active {
background-color: #409eff;
color: #fff;
cursor: not-allowed;
}
&.disabled {
cursor: not-allowed;
color: #ccc;
}
}
}
</style>
网友评论