目前下滑,已经可以看到详情图、尺码表、生产地址尺寸等、推荐等。之前做的详情页的navbar就存在着”商品“、“参数”、“讨论”与“推荐”四个模块。那么,现在想要实现的功能,即为点击navbar中的某一块,即可跳转到相应的位置。




那么,接下来即开始一个正式的实现。首先,我们之前做详情里面的navbar的时候,就已经将其封装在了一个组件里面。那我们需要把这个点击事件传到详情页主页,nav组件的代码如下:
<template>
<div class="bbb">
<navbar>
<div slot="left" class="left" @click="backclick">
<img src="../../../src/assets/img/back.svg">
</div>
<div slot="center" class="title">
<div v-for="(item,index) in title"
class="aaa" :class="{active:index === currentIndex}" v-on:click="itemclick(index)">
{{item}}
</div>
</div>
</navbar>
</div>
</template>
<script>
import Navbar from "../../../src/components/common/navbar/navbar";
export default {
name: "detailnav",
components: {Navbar},
data(){
return{
title:['商品','参数','讨论','推荐'],
currentIndex:0
}
},
methods:{
itemclick(index){
this.currentIndex = index
this.$emit("itemclick",index)
},
backclick(){
this.$router.back()
}
}
}
</script>
<style scoped>
.title{
display: flex;
font-size: 13px;
}
.aaa{
flex: 1;
}
.active{
color: greenyellow;
}
.left img{
margin-top: 10px;
}
.bbb{
background-color: #f6f6f6;
/*height: 100vh;*/
}
</style>
之后,我们在detail.vue中对其进行一个监听:
<detailnav class="nav" @itemclick="itemclick"></detailnav>
itemclick(index) { console.log(index); this.$refs.scroll.scrollTo(0, -this.themeTopY[index], 1000) }
data() {
return {
themeTopY:[ ]
}
}
初始化themeTopY数组,计算出每一个模块的相应offsetTop,将其传入空数组中,然后在上述的itemclick事件中,执行scrollTo函数到相应的选项中即可。
添加每个模块的offsetTop还是很清晰的,有两种方法,最开始想的push,后面反应过来直接赋值好像更简单哈哈哈,都可。
this.themeTopY =[ ] this.themeTopY.push(0) this.themeTopY.push(this.$refs.params.$el.offsetTop) this.themeTopY.push(this.$refs.comment.$el.offsetTop) this.themeTopY.push(this.$refs.recommend.$el.offsetTop)
或者,直接设置themeTopY= [0,0,0,0],之后在其中给每个赋值即可。
this.themeTopY[0] = 0 this.themeTopY[1] = this.$refs.params.$el.offsetTop this.themeTopY[2] = this.$refs.comment.$el.offsetTop this.themeTopY[3] = this.$refs.recommend.$el.offsetTop
之后我测试了几次在各个位置,created当中是肯定不行的,直接否认,压根获取不了元素。
mounted当中也不行,数据还没有获得到;获取到数据的回调中也不行,DOM还没有渲染完毕;$nextTick也不行,因为图片的高度没有被计算在里面。
因此,最后我把它放入了refresh()之后,终于实现哈哈哈。
<template>
<div id="detail">
<detailnav class="nav" @itemclick="itemclick"></detailnav>
<scroll class="content" ref="scroll">
<detailswiper :top-images="topImages"></detailswiper>
<detailbaseinfo :good="good"></detailbaseinfo>
<detailshopinfo :shop="shop"></detailshopinfo>
<detailgoods :detail-info="detailInfo" @imageload="imageLoad"></detailgoods>
<detailparaminfo :param-info="paramInfo" ref="params"></detailparaminfo>
<detailcommentinfo :comment-info="commentInfo" ref="comment"></detailcommentinfo>
<goodslist :goods="recommends" ref="recommend"></goodslist>
</scroll>
</div>
</template>
<script>
import Detailnav from "./childcomponent/detailnav";
import {getdetails, Good, GoodsParam, shop,getrecommend} from "../../network/detail";
import detailswiper from "./childcomponent/detailswiper";
import detailbaseinfo from "./childcomponent/detailbaseinfo";
import detailshopinfo from "./childcomponent/detailshopinfo";
import scroll from "../../src/components/common/scroll/scroll";
import detailgoods from "./childcomponent/detailgoods";
import detailparaminfo from "./childcomponent/detailparaminfo";
import detailcommentinfo from "./childcomponent/detailcommentinfo";
import goodslist from "../../src/components/content/goods/goodslist";
import {debounce} from "../../src/components/common/utils/utils";
export default {
name: "detail",
components: {Detailnav, detailswiper,detailbaseinfo,detailshopinfo,scroll,detailgoods,detailparaminfo,detailcommentinfo,goodslist},
data() {
return {
iid: null,
topImages: [],
good:{ },
shop:{ },
detailInfo:{},
paramInfo:{ },
commentInfo:{ },
recommends:[ ],
refresh: undefined,
themeTopY:[0, 0, 0, 0]
}
},
created() {
this.getdetails()
this.getrecommend()
// // console.log(this.$route.params.iid)
// this.iid = this.$route.params.iid
// getdetails(this.iid).then(res => {
// console.log(res);
// const big = res.data.result;
// this.topImages = big.itemInfo.topImages
// console.log(this.topImages)
// this.good = new Good(big.itemInfo, big.columns, big.shopInfo)
// this.shop = new shop(big.shopInfo)
// this.detailInfo = big.detailInfo
// this.paramInfo = new GoodsParam(big.itemParams.info, big.itemParams.rule );
// if (big.rate.list){
// this.commentInfo = big.rate.list[0]
// }
// })
// getrecommend().then(res =>{
// console.log(res)
// this.recommends = res.data.data.list
// }
//
// )
// this.$nextTick(()=>{
// this.themeTopY =[ ]
// this.themeTopY.push(0)
// this.themeTopY.push(this.$refs.params.$el.offsetTop)
// this.themeTopY.push(this.$refs.comment.$el.offsetTop)
// this.themeTopY.push(this.$refs.recommend.$el.offsetTop)
// console.log(this.themeTopY)
// })
// activated() {
// this.iid = this.$route.params.iid
// console.log(this.$route.params.iid)
//
// })
// }
},
mounted(){
this.refresh = debounce(this.$refs.scroll.refresh, 1000)
},
updated() {
// this.themeTopY =[ ]
// this.themeTopY.push(0)
// this.themeTopY.push(this.$refs.params.$el.offsetTop)
// this.themeTopY.push(this.$refs.comment.$el.offsetTop)
// this.themeTopY.push(this.$refs.recommend.$el.offsetTop)
// // this.themeTopY.push(Number.MAX_VALUE)
// console.log(this.themeTopY)
},
methods: {
imageLoad() {
this.refresh()
// console.log("refresh no debounce")
// this.themeTopY =[ ]
// this.themeTopY.push(0)
// this.themeTopY.push(this.$refs.params.$el.offsetTop)
// this.themeTopY.push(this.$refs.comment.$el.offsetTop)
// this.themeTopY.push(this.$refs.recommend.$el.offsetTop)
this.themeTopY[0] = 0
this.themeTopY[1] = this.$refs.params.$el.offsetTop
this.themeTopY[2] = this.$refs.comment.$el.offsetTop
this.themeTopY[3] = this.$refs.recommend.$el.offsetTop
console.log(this.themeTopY)
},
itemclick(index) {
console.log(index);
this.$refs.scroll.scrollTo(0, -this.themeTopY[index], 1000)
},
getdetails(){
this.iid = this.$route.params.iid
getdetails(this.iid).then(res => {
console.log(res)
const big = res.data.result
this.topImages = big.itemInfo.topImages
console.log(this.topImages)
this.good = new Good(big.itemInfo, big.columns, big.shopInfo)
this.shop = new shop(big.shopInfo)
this.detailInfo = big.detailInfo
this.paramInfo = new GoodsParam(big.itemParams.info, big.itemParams.rule );
if (big.rate.list) {
this.commentInfo = big.rate.list[0]
}
// this.$nextTick(()=>{
// this.themeTopY =[ ]
// this.themeTopY.push(0)
// this.themeTopY.push(this.$refs.params.$el.offsetTop)
// this.themeTopY.push(this.$refs.comment.$el.offsetTop)
// this.themeTopY.push(this.$refs.recommend.$el.offsetTop)
// // this.themeTopY.push(Number.MAX_VALUE)
// console.log(this.themeTopY)
// })
})
},
getrecommend(){
getrecommend().then(res =>{
console.log(res)
this.recommends = res.data.data.list
})
}
}
}
</script>
<style scoped>
#detail{
position: relative;
z-index:9;
background-color: #f6f6f6;
height: 100vh;
}
.content{
/*height: calc(100vh - 44px);*/
position: absolute;
top: 44px;
bottom: 60px;
}
.nav{
position: relative;
z-index: 9;
}
</style>
这里就基本实现了,但是还是有个问题,每次点击navbar中相应的模块的时候,都会挡住一些navbar中后三个模块的高度。(因为我最开始把滚动模块设定了relative,且把height设定为calc(100vh - 44px) ,因此后期我把其设置为绝对定位,固定其top:44px,bottom:60px则可以实现啦~