vue实战-产品详情页(轮播图、放大镜)
vue实战-产品详情页(轮播图、放大镜)
1.添加产品详情页的静态组件
因为它是路由组件,将其放入pages文件夹下。
注册路由组件
1)router中添加Detail的路由。
{
path:'/detail/:skuid',
component:Detail,
meta:{show:true}
},
2)在Search页面处的产品点击跳转处,设置声明式导航跳转
<router-link :to="`/detail/${good.id}`">
<img :src="good.defaultImg" />
</router-link>
2.设置详情页的api接口
在文件夹api下的接口统一管理中添加获得接口数据的函数reqDetailInfo,
需要传入产品的ID
// /api/item/{ skuId }
export const reqDetailInfo = (skuId) =>{
return requests({url:`/item/${skuId}`,method:'get'})
}
3.创建关于产品详情的仓库(vuex)
在文件夹store下
import { reqDetailInfo } from "@/api"
const state = {
detailList:{}
}
const mutations = {
GETDETAILLIST(state,detailList){
state.detailList = detailList
}
}
const actions = {
async getDetailList({commit},skuid){
let result = await reqDetailInfo(skuid)
if(result.code==200){
commit('GETDETAILLIST',result.data)
}
}
}
const getters = {
categoryView(state){
return state.detailList.categoryView
},
skuInfo(state){
return state.detailList.skuInfo
},
spuSaleAttrList(state){
return state.detailList.spuSaleAttrList
}
}
export default {
state,
mutations,
actions,
getters
}
在Detail组件下派发actions,触发数据进库。
mounted() {
this.$store.dispatch("getDetailList", this.$route.params.skuid);
},
通过getters处理,组件获得仓库中的数据
import { mapGetters } from "vuex";
computed: {
...mapGetters([ "categoryView", "skuInfo", "spuSaleAttrList" ]),
}
4.动态数据展示
左侧导航处
<!-- 导航路径区域 -->
<div class="conPoin">
<span v-show="categoryName.category1Name">{{
categoryName.category1Name
}}</span>
<span v-show="categoryName.category2Name">{{
categoryName.category2Name
}}</span>
<span v-show="categoryName.category3Name">{{
categoryName.category3Name
}}</span>
</div>
放大镜与轮播图
父组件
<!--放大镜效果-->
<Zoom :skuImageList="skuInfos" />
<!-- 小图列表 -->
<ImageList :skuImageList="skuInfos" />
轮播图
轮播图子组件
<div class="swiper-container" ref="cur">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="(skuImage,index) in skuImageList.skuImageList" :key="skuImage.id">
<img :src="skuImage.imgUrl" :class="{active:currentIndex==index}" @click="changeCurrentIndex(index)">
</div>
</div>
<div class="swiper-button-next"></div>
<div class="swiper-button-prev"></div>
</div>
传值以及逻辑控制、动态轮播图
import Swiper from 'swiper'
export default {
name: "ImageList",
data() {
return {
currentIndex:0
}
},
props:[ 'skuImageList' ],
//轮播图监听
watch:{
skuImageList:{
immediate:true,
handler(){
this.$nextTick(()=>{
new Swiper (this.$refs.cur, {
// 如果需要前进后退按钮
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
slidesPerView:3,
slidesPerGroup:1
})
})
}
}
},
methods: {
changeCurrentIndex(index){
this.currentIndex = index
//全局事件总线传值给兄弟组件zoom组件,判断此时点击的是哪张图片
this.$bus.$emit('getIndex',this.currentIndex)
}
},
}
放大镜
子组件
<template>
<div class="spec-preview">
<img :src="imgObj.imgUrl" />
<div class="event" @mousemove="handler"></div>
<div class="big" >
<img :src="imgObj.imgUrl" ref="big" />
</div>
<div class="mask" ref="ms"></div>
</div>
</template>
放大镜逻辑设置、参数动态传递逻辑
export default {
name: "Zoom",
data() {
return {
currentIndex:0
}
},
props:[ 'skuImageList' ],
computed:{
//防止传来的值还没有值,用一个空数组来代替
imgObj(){
return this.skuImageList.skuImageList[this.currentIndex] || []
}
},
//全局事件总线的绑定
mounted(){
this.$bus.$on('getIndex',(index)=>{
this.currentIndex = index
})
},
methods: {
//放大镜核心函数
handler(event){
let mask = this.$refs.ms
let big = this.$refs.big
let left = event.offsetX - mask.offsetWidth/2
let top = event.offsetY - mask.offsetHeight/2
if(left < 0) left = 0
if(left >= mask.offsetWidth) left = mask.offsetWidth
if(top < 0) top = 0
if(top >= mask.offsetHeight) top = mask.offsetHeight
//修改mask的属性值
mask.style.left = left+'px'
mask.style.top = top+'px'
big.style.left = -2*left +'px'
big.style.top = -2*top + 'px'
}
},
}