关于详情页的具体制作(五)

目前下滑,已经可以看到详情图、尺码表、生产地址尺寸等、推荐等。之前做的详情页的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则可以实现啦~

原文地址:https://www.cnblogs.com/ljylearnsmore/p/14302807.html