1. 程式人生 > 實用技巧 >關於詳情頁的具體制作(六)

關於詳情頁的具體制作(六)

已經實現了,點選詳情頁navbar的四個模組,會對應到每個商品中的相應位置。那麼,我們現在想實現的是:比如滾到相應的尺寸模組或者評論時,navbar上的詳情或者排列會自動變色。

這個,主要用了以下思路來實現:

首先,我們可以用一種很直觀的方式來表達,首先先在scroll標籤中設定probeType為3(因為在原來封裝scroll的時候,將probeType的預設值設定為0,設定為3的時候可方便滾動且實時監聽他的位置)

 <scroll class="content" ref="scroll" @scroll="contentscroll" :probe-type="3">

之前在scroll.vue中曾經設定過監聽滾動的位置的時候,傳送出scroll事件,那麼在此標籤中,將監聽contentscroll事件。

那麼,接下來我們來講述下contentscroll事件應該如何設計,首先是比較複雜的邏輯關係的設定。首先回顧下,我們把一個在data中初始化一個數組themeTopY,且在imageLoad中,每次都push了每個模組的offsetTop值。

 data() {
    return {
      themeTopY:[0,0,0,0],
      currentIndex:0
    }
  }
 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) console.log(this.themeTopY) }

且,溫故下原來封裝的scroll:

<template>
<div class="wrapper" ref="wrapper">
 <div class="content">
   <slot></slot>
 </div>
</div>
</template>
<!--//
ref如果是繫結在元件中的,那麼通過this.$refs.refname獲取到的是一個元件物件--> <!--//ref如果繫結在普通元素中,那麼會通過this.$refs.refname獲取的一個元素物件--> <script> import BScroll from "better-scroll" export default { name: "scroll", props:['probeType',"pullUpLoad"], //'pullUpLoad' data(){ return{ scroll:null } }, mounted(){ //1.建立BScroll物件 this.scroll = new BScroll(this.$refs.wrapper,{ click:true, probeType:this.probeType, pullUpLoad:this.pullUpLoad //監聽滾動到底部 }) // this.scroll.scrollTo(0,0) //2.監聽滾動的位置 this.scroll.on("scroll",(position)=>{ // console.log(position); this.$emit("scroll",position) }) //3.監聽上拉載入事件 // this.scroll.on("pullingUp",()=>{ // this.$emit("pullingUp") // }) //監聽滾動到底部 if(this.pullUpLoad){ this.scroll.on("pullingUp",()=>{ // console.log("監聽"); this.$emit("pullingUp") }) } }, methods: { scrollTo(x, y, time = 1000) { this.scroll.scrollTo(x, y, time) }, // finishPullUp(){ // this.scroll.finishPullUp() // }, refresh() { // console.log("----1----"); this.scroll.refresh() }, finishPullUp() { }, // }, getScrollY() { return this.scroll ? this.scroll.y : 0 } } } </script> <style scoped> </style>

後期,我們來處理下detail.vue中的contentscroll事件:

 contentscroll(position){
      // console.log(position);
      const positionY = -position.y
      for(let i= 0;i<this.themeTopY.length;i++){
        if(this.currentIndex !== i && i< this.themeTopY.length -1 && positionY >= this.themeTopY[i] && positionY < this.themeTopY[i+1] ||
          (i === this.themeTopY.length - 1 && positionY > this.themeTopY[i])){
          this.currentIndex = i;
          console.log(this.currentIndex);
          this.$refs.nav.currentIndex = i
        }
      }

解釋下上述的程式碼:

首先,我們設定positionY為y軸上的position,由於其值在我測試後顯示為負值,所以我直接在前面添加了一個負號。

之後,設定了一個for迴圈,設定i小於themeTopy的長度。之後,我主要做了一個或邏輯,來處理它。左邊,我設定,i小於themeTopY的長度,且當positionY大於等於i的offsetTop值,小於下標i+1的offsetTop值的時候,

可以執行;或者i等於themeTopY的長度值減1的時候,也就是themeTopY的最後一個下標,且positionY大於最後一個數組元素的offsetTop時 ,也可以執行相應語句。之後,我在data中初始化了一個currentIndex,且在或邏輯的左邊,設定當currentIndex的值不等於i的時候,才會執行相應左邊的語句。之後,在執行時,我將i值賦予currentIndex,且將i值賦予navbar元件中的currentIndex值,我們再把detail中的navbar程式碼復現下:

e>
  <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>

那麼,我們可以很清晰地發現,當事件中的i值賦予給navbar中的currentIndex,那麼就可以實現滾動商品的四個詳情模組的時候,亦可以實現滾動到哪個模組就啟用navbar上的某個值。

這個方法的話,邏輯還是有點雜糅,還有個更為簡單的方法。

我們可以在themeTopY這個陣列的最後,直接push一個極大值,這樣的話,直接在每個區間中執行就ok了,那我們來看下其程式碼實現。

 imageLoad() {
      this.refresh()
        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)
    }
contentscroll(position) {
      // console.log(position);
      const positionY = -position.y
      for (let i = 0; i < this.themeTopY.length - 1; i++) {
        if (this.currentIndex !== i && (positionY >= this.themeTopY[i] && positionY < this.themeTopY[i + 1])) {
          this.currentIndex = i;
          // this.$refs.nav.currentIndex = this.currentIndex
          this.$refs.nav.currentIndex = i
        }

      }

    }

我們看下上述程式碼,當我在陣列最後push進了一個極大值的時候,我的邏輯也可以實現的很為簡潔了。首先,我們將i的值限制,限制其小於themeTop的長度-1,之後我們只需要,將positionY的值限制在大於等於陣列中i位置的offsetTop且小於i+1的位置即可。

之後我們將i值賦予給nav中的currentIndex即可實現。