vue前台(六点二)

一,分页组件连续页起始和结束计算

自定义通用的分页组件
    
    实现静态组件(模板结构样式)
        参考文档去获取

    设计数据
        外部接受的
            当前页码
            每页数量
            总数
            连续页码数量   一般都是奇数个

        自己内部的
            总页数
            连续页码的起始和结束(比较恶心)

            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全局注册分页组件

import Pagination from '@/components/Pagination'
Vue.component('Pagination',Pagination)
 
3.在search组件中实例化分页组件paginnation,

 

 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中获取数据

import { mapGetters } from "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>

 

 

 

 

 

 

posted @ 2020-07-21 06:14  全情海洋  阅读(223)  评论(0编辑  收藏  举报