vue前台(七)

 

一,在detail组件中,向子组件zoom和 imglist传递数据,属性传递,

1.父组件detail

  computed: {
    ...mapGetters(["categoryView", "skuInfo", "spuSaleAttrList",'imgList'])
  },

向子组件传递数据

<div class="previewWrap">
          <!--放大镜效果-->
          <Zoom :imgList="skuInfo.skuImageList" />
          <!-- 小图列表 -->
          <ImageList  :imgList="skuInfo.skuImageList" />
        </div>

 

 

 子组件接收

 props:['imgList'],

 

2. ,ImageList组件填充数据,底部轮播图
 <div class="swiper-container">
    <div class="swiper-wrapper">
      <div class="swiper-slide" v-for="(img, index) in imgList" :key="img.id">
        <img :src="img.imgUrl">
      </div>
    </div>
    <div class="swiper-button-next"></div>
    <div class="swiper-button-prev"></div>
  </div>

 

 

3.zoom子组件填充数据,默认呈现第一张图,data中初始化一个index

 data(){
      return {
        defaultIndex : 0
      }

大图填充数据

<div class="spec-preview">
    <img :src="imgList[defaultIndex].imgUrl" />
    <div class="event"></div>
    <div class="big">
      <img :src="imgList[defaultIndex].imgUrl"  />
    </div>
    <div class="mask"></div>
  </div>

 

 

注;此时控制台会报错, a.b.c假报错问题, 

 

 

解决方式,此时需要判断imglist

 computed:{
      //计算它的可能值,不然出现a.b.c
      defaultImg(){
        if(this.imgList){
          return this.imgList[this.defaultIndex]
        }else{
          return {}
        }
      }
    }

 

 再次填充数据

  <div class="spec-preview">
    <img :src="defaultImg.imgUrl" />
    <div class="event"  @mousemove="move"></div>
    <div class="big">
      <img :src="defaultImg.imgUrl" ref="bigImg"/>
    </div>
    <div class="mask" ref="mask"></div>
  </div>

 

 

二,小图列表点击,切换类

1.在imageslist组件中定义初始索引,当点击轮播图的图片时,index赋值给currentIndex,类名也跟着动态展示,此时将轮播图的index传递给大图组件,轮播图展示哪张图,大图也跟着

展示哪张图

  data() {
    return {
      currentIndex: 0
    };
  },

类名

.active {
        border: 2px solid #f60;
        padding: 1px;
      }

2.点击小图,切换类

 <div class="swiper-slide" v-for="(img, index) in imgList" :key="img.id">
        <img :src="img.imgUrl" @click="changeIndex(index)" :class="{active:currentIndex === index}" />
      </div>

回调函数,跟新索引,

  methods: {
    changeIndex(index) {
      this.currentIndex = index;

 

三,点击小图,切换一样的中图

1.在imagelist中点击小图,回调中传递index,用全局事件总线传递index,传递给兄弟组件zoom

<div class="swiper-slide" v-for="(img, index) in imgList" :key="img.id">
        <img :src="img.imgUrl" @click="changeIndex(index)" :class="{active:currentIndex === index}" />
      </div>

点击事件回调函数,搞事件总线,$emitc触发,传递index给zoom大图组件

  methods: {
    changeIndex(index) {
      this.currentIndex = index;
      this.$bus.$emit("changeDefaultIndex", index);
    }
  },

 

在zoom组件中,监听

  mounted(){
      this.$bus.$on('changeDefaultIndex',this.changeDefaultIndex)
    },

回调函数,跟新当前索引

 methods:{
      changeDefaultIndex(index){
        this.defaultIndex = index
      },

 

四,小图片的轮播图处理

 

1.html模板

 <div class="swiper-container" ref="imglist">
    <div class="swiper-wrapper">
      <div class="swiper-slide" v-for="(img, index) in imgList" :key="img.id">
        <img :src="img.imgUrl" @click="changeIndex(index)" :class="{active:currentIndex === index}" />
      </div>
    </div>
    <div class="swiper-button-next"></div>
    <div class="swiper-button-prev"></div>
  </div>

 

2.引入swiper

import Swiper from "swiper";
import "swiper/css/swiper.min.css";

3. 在实例化swiper

  watch: {
    imgList: {
      handler() {
        //Vue.nextTick或者vm.$nextTick是一样的功能
        //在最近的一次dom更新之后执行nextTick里面传的回调函数
        this.$nextTick(() => {
          new Swiper(this.$refs.imglist, {
            // direction: "vertical", // 垂直切换选项
            // autoplay:true,//等同于以下设置
            // loop: true, // 循环模式选项

            // // 如果需要分页器
            // pagination: {
            //   el: ".swiper-pagination"
            // },

            // 如果需要前进后退按钮
            navigation: {
              nextEl: ".swiper-button-next",
              prevEl: ".swiper-button-prev"
            },
            slidesPerGroup:5, //点击一下滑动一组有多少张
            slidesPerView:5 //一屏显示多少张
            // 如果需要滚动条
            // scrollbar: {
            //   el: ".swiper-scrollbar"
            // }
          });
        });
      },
      immediate: true //立即执行,在最近dom更新之前就会执行
    }
  }

 

 五,放大镜逻辑

 

1.在图片中添加移动事件,获取鼠标的坐标,并且确定遮罩mask需要移动的距离,以及对应的大图移动的距离

在zoom组件中, html中

<template>
  <div class="spec-preview">
    <img :src="defaultImg.imgUrl" />
    <div class="event"  @mousemove="move"></div>
    <div class="big">
      <img :src="defaultImg.imgUrl" ref="bigImg"/>
    </div>
    <div class="mask" ref="mask"></div>
  </div>
</template>

js代码

 // 图片移动事件
      move(event){
        let target = event.target    //拿的是事件源元素
        let mouseX = event.offsetX   //鼠标相对事件源本身的x位置
        let mouseY = event.offsetY   //鼠标相对事件源本身的y位置
        let mask = this.$refs.mask
        let bigImg = this.$refs.bigImg
        //求mask 要走的位置
        let maskX = mouseX - mask.offsetWidth / 2
        let maskY = mouseY - mask.offsetHeight / 2

        if(maskX < 0){
          maskX = 0
        }else if(maskX > target.clientWidth - mask.offsetWidth){
          maskX = target.clientWidth - mask.offsetWidth
        }

        if(maskY < 0){
          maskY = 0
        }else if(maskY> target.clientHeight- mask.offsetHeight){
          maskY = target.clientHeight - mask.offsetHeight
        }


        //设置mask的位置
        mask.style.left = maskX + 'px'
        mask.style.top = maskY + 'px'

        //设置大图的移动位置,mask移动相反的两倍
        bigImg.style.left = -2 *maskX + 'px'
        bigImg.style.top = -2 *maskY + 'px'
      }

 

六, 对产品的属性的方框进行选中处理

1.  isChecked属性为选中的标识,‘1’为选中, ‘0’为不选中

在detail组件中

html代码

  <dl v-for="(item, index) in spuSaleAttrList" :key="index">
                <dt class="title">{{item.saleAttrName}}</dt>
                <dd
                  changepirce="0"
                  :class="{active:attrValue.isChecked === '1'}"
                  v-for="(attrValue, index) in item.spuSaleAttrValueList"
                  :key="attrValue.id"
                  @click="changeIsCheck(item.spuSaleAttrValueList,index)"
                >{{attrValue.saleAttrValueName}}</dd>
              </dl>

2.对选中的方框排他处理

js代码

  changeIsCheck(attrValueList,index){
      //排它
      attrValueList.forEach(item => {
        item.isChecked = '0'
      })
      attrValueList[index].isChecked = '1'
    },

 

七, 修改购买的数量的v-model的应用,收集数量,点击加号,减号,增减数量

<div class="controls">
                <input autocomplete="off" class="itxt" v-model="skuNum"/>
                <a href="javascript:" class="plus" @click="skuNum++">+</a>
                <a href="javascript:" class="mins" @click="skuNum <= 1 ? 1 : skuNum-- ">-</a>
              </div>

 

八, 点击添加购物车时发送请求,是否添加成功

1.封装请求添加购物车的请求

//请求添加购物车  /api/cart/addToCart/{ skuId }/{ skuNum }    post

export const reqAddOrUpdateShopCart = (skuId,skuNum) => Ajax.post(`/cart/addToCart/${ skuId }/${ skuNum }`)

 

2.配置shopcart.js的vuex

import {reqAddOrUpdateShopCart} from '@/api'

const state = {
}
const mutations = {
}

const actions = {
  async addorUpdateShopCart({commit},{skuId,skuNum}){
    const result = await reqAddOrUpdateShopCart(skuId,skuNum)
    if(result.code === 200){
      return '添加购物车成功'
    }else{
      // return '添加购物车失败' 返回的还是成功的promise
      //返回的是失败的promise
      return Promise.reject(new Error('添加购物车失败'))
    }
  }
}

const getters = {
}

export default {
  state,
  mutations,
  actions,
  getters
}

3.在总vuex中注册

4.在添加购物车按钮中,添加点击事件
 <div class="add">
                <a href="javascript:" @click="toSuccess">加入购物车</a>
              </div>

5, js代码,添加商品请求成功后,需要把商品存储在本地浏览器sessionStorage, 商品的数量用路由传参,然后路由组件

跳转到产品添加成功页面

 
 async toSuccess(){
      //先发请求,判定是否成功
      //调用我们actions内部的异步函数(async),这个调用的返回值一定是一个promise
      try {
        const result = await this.$store.dispatch('addorUpdateShopCart',{skuId:this.skuInfo.id,skuNum:this.skuNum})
        alert(result)
        //在添加成功跳转到添加成功页面之前,把相应的商品存储在sessionStorage当中,用来在添加成功页面去使用
        //本地存储传参
        sessionStorage.setItem('SKUINFO_KEY',JSON.stringify(this.skuInfo))

        this.$router.push(`/addcartsuccess?skuNum=${this.skuNum}`)  //如果添加购物车成功,那么就跳转到添加购物车成功的页面

         //路径传参给路由组件
        // this.$router.push({name:'addcartsuccess', query:{skuNum:this.skuNum,skuInfo:this.skuInfo }})
      } catch (error) {
        alert(error.message)
      }
      
      //成功
      //失败
    }

 

6,跳转到商品添加成功页面AddCartSuccess,填充传递过来的数据

<div class="right-info">
            <p class="title">{{skuInfo.skuName}}</p>
            <p class="attr">颜色:WFZ5099IH/5L钛金釜内胆 数量:{{$route.query.skuNum}}</p>
          </div>
data(){
      return {
        skuInfo: JSON.parse(sessionStorage.getItem('SKUINFO_KEY')) || {}
      }
    },

 

7.路由连接到查看商品详情页
<router-link :to="`/detail/${skuInfo.id}`" class="sui-btn btn-xlarge">查看商品详情</router-link>

 

 

 

 

 

 

 

 

 

 

 

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