關於詳情頁的具體制作(六)
已經實現了,點選詳情頁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即可實現。