一,分页组件连续页起始和结束计算
自定义通用的分页组件
实现静态组件(模板结构样式)
参考文档去获取
设计数据
外部接受的
当前页码
每页数量
总数
连续页码数量 一般都是奇数个
自己内部的
总页数
连续页码的起始和结束(比较恶心)
1、先判断连续页码是不是比最大的页码还要大,如果是那么start=1 end就是最大页码
2、如果连续页码比最大页码小
我们让start = 当前页码 - 连续页码/2 取整
end = 当前页码 + 连续页码/2 取整
如果start 求出来比1还小 那么start修正为1 end需要+修正的偏移量
如果end 求出来比最大页码还大 同样end修正为最大页码 start - 修正的偏移量
自定义通用的分页组件
1、去课件当中获取到分页的静态组件
2、注册组件并渲染静态组件
3、动态组件的逻辑和功能
3-1:思考设计 分页组件所需要的从父组件传递的数据是那些(1、当前页码 2、每页数量 3、总数 4、连续页数)
3-2:思考设计 分页内部需要计算的数据:总页数 连续页码的起始和结束
3-3:在分页当中开始去计算逻辑
1.在component中创建分页组件paginnation,
2.在入口文件main.js全局注册分页组件
data() {
return {
//初始化搜索参数(收集搜索参数)
//为搜索请求提供搜索参数
searchParams: {
category1Id: "",
category2Id: "",
category3Id: "",
categoryName: "",
keyword: "",
order: "2:desc", //排序标志:排序类型 1代表综合排序 2代表价格排序 asc升序 desc降序
// 当前页码数
pageNo: 1,
// 每页图片数
pageSize: 4,
props: [],
trademark: ""
},
};
},
4.1,父子通信,search组件的数据传递给子组件paginnation,传递当前页,每页条数,总条数,连续页数,
<Pagination :currentPageNum="searchParams.pageNo" :pageSize="searchParams.pageSize" :total="goodsListInfo.total" :continueNum="5" @changePage="changePageNum"> </Pagination>
4.2,.pagination组件props接收数据,default为默认值,
props:{
// 当前页码数
currentPageNum:{
type:Number,
default:1
},
//每页图片数
pageSize:{
type:Number,
default:10
},
//总图片数
total:{
type:Number,
default:0
},
// 连续页码数量
continueNum:{
type:Number,
default:5
}
},
4.3,连续页码起始和结束计算
computed:{ //计算总页数,有所少页,总图片数 / 每页图片数,向上取整 totalPage(){ return Math.ceil(this.total / this.pageSize) }, //计算连续页的起始和结束 startEnd(){ let {currentPageNum,totalPage,continueNum} = this let start let end let disNum //第一步:判断总页码是否比连续页码还要小 if(totalPage <= continueNum){ start = 1 end = totalPage }else{ //正常情况,向下取整 start = currentPageNum - Math.floor(continueNum / 2) end = currentPageNum + Math.floor(continueNum / 2) //左边界限制,start if(start <= 1){
//计算间隔 disNum = 1- start start += disNum end += disNum } //右边界限制 if(end >= totalPage ){ disNum = end - totalPage start -= disNum end -= disNum } } return {start,end} } }
二,分页器模板动态页码数据及背景展示
类名
.active {
cursor: not-allowed;
background-color: #409eff;
color: #fff;
}
动态页码展示
注;连续页码用v-for, 并且page要大于start,
<template> <div class="pagination"> <button :disabled="currentPageNum === 1" @click="$emit('changePage',currentPageNum - 1)">上一页</button> <!-- 1平时是一直显示的,只有当start的值和1一样,那么1就不显示,而是显示start的1 --> <button v-show="startEnd.start > 1" :class="{active:currentPageNum === 1}" @click="$emit('changePage',1)">1</button> <button v-show="startEnd.start > 2">···</button> <!-- 如果v-for和v-if同时存在,v-for优先级比v-if要高 --> <button v-for="page in startEnd.end" :key="page" v-if="page >= startEnd.start" :class="{active:page === currentPageNum}" @click="$emit('changePage',page)" >{{page}}</button> <button v-show="startEnd.end < totalPage - 1">···</button> <button v-show="startEnd.end < totalPage" :class="{active:currentPageNum === totalPage}" @click="$emit('changePage',totalPage)">{{totalPage}}</button> <button :disabled="currentPageNum === totalPage" @click="$emit('changePage',currentPageNum + 1)">下一页</button> <button style="margin-left: 30px">共 {{total}} 条</button> </div> </template>
三,点击页码的交互逻辑(跟新父组件页码参数,重新发请求),自定义事件,父子通信,
用户点击当前页,pagintation子组件触发事件,传递currentPageNum当前页参数给search,重新发送请求
<template> <div class="pagination"> <button :disabled="currentPageNum === 1" @click="$emit('changePage',currentPageNum - 1)">上一页</button> <!-- 1平时是一直显示的,只有当start的值和1一样,那么1就不显示,而是显示start的1 --> <button v-show="startEnd.start > 1" :class="{active:currentPageNum === 1}" @click="$emit('changePage',1)">1</button> <button v-show="startEnd.start > 2">···</button> <!-- 如果v-for和v-if同时存在,v-for优先级比v-if要高 --> <button v-for="page in startEnd.end" :key="page" v-if="page >= startEnd.start" :class="{active:page === currentPageNum}" @click="$emit('changePage',page)" >{{page}}</button> <button v-show="startEnd.end < totalPage - 1">···</button> <button v-show="startEnd.end < totalPage" :class="{active:currentPageNum === totalPage}" @click="$emit('changePage',totalPage)">{{totalPage}}</button> <button :disabled="currentPageNum === totalPage" @click="$emit('changePage',currentPageNum + 1)">下一页</button> <button style="margin-left: 30px">共 {{total}} 条</button> </div> </template>
search父组件,绑定自定义事件,接收子传过来的参数,发送请求
<Pagination :currentPageNum="searchParams.pageNo" :pageSize="searchParams.pageSize" :total="goodsListInfo.total" :continueNum="5" @changePage="changePageNum"> </Pagination>
changePageNum(num){
this.searchParams.pageNo = num
this.getGoodsListInfo();
}
注:用户搜索条件改变,让其变成第一页,然后发送请求
四,search中商品详情静态页面的展示及路由滚动行为
在pages中创建deteil组件,在router.js引入,注册,路径
export default [
{
path:'/detail/:goodsId',
component:Detail
},
设置路由连接
<li class="yui3-u-1-5" v-for="(goods, index) in goodsList" :key="goods.id"> <div class="list-wrap"> <div class="p-img"> <router-link :to="`/detail/${goods.id}`"> <img :src="goods.defaultImg" /> </router-link> </div> <div class="price"> <strong> <em>¥</em> <i>{{goods.price}}</i> </strong> </div> <div class="attr"> <a target="_blank" href="item.html" title="促销信息,下单即赠送三个月CIBN视频会员卡!【小米电视新品4A 58 火爆预约中】" >{{goods.title}}</a> </div> <div class="commit"> <i class="command"> 已有 <span>2000</span>人评价 </i> </div> <div class="operate"> <a href="success-cart.html" target="_blank" class="sui-btn btn-bordered btn-danger" >加入购物车</a> <a href="javascript:void(0);" class="sui-btn btn-bordered">收藏</a> </div> </div> </li>
此时,跳转到detail组件中,但是没有跳转到页面顶部,需要配置下滚动行为,在router中
export default new VueRouter({
routes,
scrollBehavior (to, from, savedPosition) {
return { x: 0, y: 0 }
}
})
五,此时detail中要获取商品的动态数据,需要请求接口
1.在api中封装接口函数
//请求商品详情数据
// /api/item/{ skuId } get
export const reqGoodsDetailInfo = (skuId) => Ajax.get(`/item/${ skuId }`)
2.创建detail的vuex
import {reqGoodsDetailInfo} from '@/api'
const state = {
goodsDetailInfo : {}
}
const mutations = {
//直接修改数据
RECEIVEGOODSDETAILINFO(state,goodsDetailInfo){
state.goodsDetailInfo = goodsDetailInfo
},
}
const actions = {
//异步请求数据
//async 和 await的用法
async getGoodsDetailInfo({commit},skuId){
const result = await reqGoodsDetailInfo(skuId)
if(result.code === 200){
commit('RECEIVEGOODSDETAILINFO',result.data)
}
},
}
const getters = {
categoryView(state){
return state.goodsDetailInfo.categoryView || {}
},
skuInfo(state){
return state.goodsDetailInfo.skuInfo || {}
},
spuSaleAttrList(state){
return state.goodsDetailInfo.spuSaleAttrList || []
}
}
export default {
state,
mutations,
actions,
getters
}
3.在总的vuex注册
export default new Vuex.Store({
state,
mutations,
actions,
getters,
modules:{
home,
search,
detail
}
})
4.在detail组件中关联vuex, 发送请求,
mounted() {
this.getGoodsDetailInfo();
},
methods: {
getGoodsDetailInfo() {
this.$store.dispatch("getGoodsDetailInfo", this.$route.params.goodsId);
}
},
5.从vuex中获取数据
computed: {
...mapGetters(["categoryView", "skuInfo", "spuSaleAttrList"])
},
6.向htm模板中填充数据
<!-- 导航路径区域 --> <div class="conPoin"> <span>{{categoryView.category1Name}}</span> <span>{{categoryView.category2Name}}</span> <span>{{categoryView.category3Name}}</span> </div>
<div class="chooseArea"> <div class="choosed"></div> <dl v-for="(item, index) in spuSaleAttrList" :key="index"> <dt class="title">{{item.saleAttrName}}</dt> <dd changepirce="0" class="active" v-for="(attrValue, index) in item.spuSaleAttrValueList" :key="attrValue.id" >{{attrValue.saleAttrValueName}}</dd> </dl> </div>