Vue仿京東移動端web版商品詳情頁滾動樣式
要求:
- 頁面頂部固定有 商品、評價、推薦、詳情四個選項卡,對應四個部分的內容。
- 商品:顯示輪播圖、標題、價格等;評價:顯示4條精選評價;推薦:顯示兩行三列6條推薦信息;詳情:商品的詳細介紹通常為富文本或一系列圖片。
- 手動滾動頁面,導航選項欄同樣會自動切換對應樣式。
- 當頁面滾動距離為0時,導航選項欄透明度為0,且不可點擊,每往下滾動20增加0.1,大於等於200時一直為1。(考慮性能可改為無級自動透明度或者每40增加0.2)
- 點任意選項卡會切換樣式且滾動到對應的內容位置,
- 點擊導航欄商品選項卡時時,滾動到0且透明度直接為0
預覽效果
http://vietechen.gitee.io/jd/product/product.html
綁定滾動事件
mounted() { window.addEventListener('scroll', this.handleScroll); }, methods: { // 監聽頁面滾動 handleScroll () { var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop } }
獲取組件標簽的位置
<div class="comment" ref="comment" id="comment"></div> /**/ let recommendTop = this.$refs.comment.offsetTop - 45;
使頁面滾動到某組件標簽
<a href="javascript:" @click="onScrollComment">評價</a> onScrollComment(){ document.documentElement.scrollTop = this.$refs.comment.offsetTop - 45; // behavior 類型String,表示滾動行為,支持參數 smooth(平滑滾動),instant(瞬間滾動),默認值auto,實測效果等同於instant window.scrollTo({top: this.$refs.detail.offsetTop - 45, behavior: "smooth" }); },
完整代碼
樣式細節未打磨,部分js代碼可自行修改優化。瘋狂滾動CPU占用比京東低。
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <title>Document</title> 9 <script src="vue.js"></script> 10 </head> 11 12 <body> 13 <div id="app"> 14 <div :style="{opacity: opacity}" class="nav"> 15 <div class="header-new-title"> 16 <nav class="detail_anchor"> 17 <a href="javascript:" dtype="item" :class="{'active': active=='goods'}" 18 @click="onScrollGoods"><span>商品</span></a> 19 <a href="javascript:" dtype="comment" :class="{'active': active=='comment'}" 20 @click="onScrollComment"><span>評價</span></a> 21 <a href="javascript:" dtype="guess" :class="{'active': active=='recommend'}" 22 @click="onScrollRecommend"><span>推薦</span></a> 23 <a href="javascript:" dtype="detail" :class="{'active': active=='detail'}" 24 @click="onScrollDetail"><span>詳情</span></a> 25 </nav> 26 </div> 27 </div> 28 29 <div class="goods"> 30 <img style="width: 100%;" src="./apple-1.jpg" alt=""> 31 <div>我是商品標題</div> 32 <div>我是商品價格</div> 33 <div v-for="(item, index) in 10" :key="index">其他</div> 34 </div> 35 <hr> 36 37 <div class="comment" ref="comment" id="comment"> 38 <div>精選評價</div> 39 <div v-for="(item, index) in 4" :key="index"> 40 <div class="title"><span class="fl">張若虛</span><span class="fr">2019-10-{{item}}</span></div> 41 <div class="content">春江潮水連海平,海上明月共潮生。</div> 42 </div> 43 </div> 44 <hr> 45 46 <div class="recommend" ref="recommend" id="recommend"> 47 <div>猜你喜歡</div> 48 <img v-for="(item, index) in 6" :key="index" style="width: 33%;" src="./apple-1.jpg" alt=""> 49 </div> 50 <hr> 51 52 <div ref="detail"> 53 <div></div> 54 <div>我是商品詳情 55 <img v-for="(item, index) in 5" :key="index" style="width: 100%;" src="./apple-1.jpg" alt=""> 56 </div> 57 </div> 58 59 <div class="de_btn_bar"> 60 <div class="btn_group"> 61 <div class="btn_group_item" style="width: 16%;">客服</div> 62 <div class="btn_group_item" style="width: 16%;">店鋪</div> 63 <div class="btn_group_item" style="width: 18%;">購物車</div> 64 <div class="btn_group_item add_cart">加入購物車</div> 65 <div class="btn_group_item now_buy">立即購買</div> 66 </div> 67 </div> 68 69 </div> 70 <script> 71 var vm = new Vue({ 72 el: '#app', 73 data: { 74 scrollTop: 0, 75 opacity: 0, 76 active: 'goods', 77 78 }, 79 // 綁定滾動事件 80 mounted() { 81 window.addEventListener('scroll', this.handleScroll); 82 }, 83 methods: { 84 // 監聽頁面滾動 85 handleScroll() { 86 // 獲取當前的滾動距離 87 var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop 88 // console.log(scrollTop) 89 90 if (scrollTop < 200) { 91 // 當滾動距離小於200時,計算導航透明度,可以考慮修改為每20增加0.1 92 // this.opacity = (scrollTop / 200).toFixed(1); 93 this.opacity = scrollTop / 200; 94 this.active = 'goods'; 95 return 96 } else { 97 this.opacity = 1 98 } 99 // 當滾動距離不小於200時,獲取三個部分的頂部位置-45。 100 let commentTop = this.$refs.comment.offsetTop - 45; 101 let recommendTop = this.$refs.recommend.offsetTop - 45; 102 let detailTop = this.$refs.detail.offsetTop - 45; 103 // 計算滾動距離在哪個區間,修改this.active對應的樣式名 104 if (scrollTop < commentTop) { if (this.active != 'goods') this.active = 'goods'; } 105 else if (scrollTop >= commentTop && scrollTop < recommendTop) { if (this.active != 'comment') this.active = 'comment'; } 106 else if (scrollTop >= recommendTop && scrollTop < detailTop) { if (this.active != 'recommend') this.active = 'recommend'; } 107 else if (scrollTop >= detailTop) { if (this.active != 'detail') this.active = 'detail'; } 108 }, 109 110 // 點擊導航欄第一個商品選項卡時,直接滾動到0 111 onScrollGoods() { 112 // document.documentElement.scrollTop = 0; 113 window.scrollTo({top: 0, behavior: "smooth" }); 114 }, 115 // 點擊導航欄其他選項卡時,直接滾動到對應ref的offsetTop-45(導航欄高度) 116 onScrollComment() { 117 if (!this.opacity) return; 118 window.scrollTo({top: this.$refs.comment.offsetTop - 45, behavior: "smooth" }); 119 }, 120 onScrollRecommend() { 121 if (!this.opacity) return; 122 window.scrollTo({top: this.$refs.recommend.offsetTop - 45, behavior: "smooth" }); 123 }, 124 onScrollDetail() { 125 if (!this.opacity) return; 126 //document.documentElement.scrollTop = this.$refs.detail.offsetTop - 45; 127 // behavior 類型String,表示滾動行為,支持參數 smooth(平滑滾動),instant(瞬間滾動),默認值auto,實測效果等同於instant 128 window.scrollTo({top: this.$refs.detail.offsetTop - 45, behavior: "smooth" }); 129 130 }, 131 }, 132 }) 133 </script> 134 <style lang="less"> 135 body { 136 margin: 0; 137 } 138 a { 139 text-decoration: none; 140 color: #252525; 141 -webkit-tap-highlight-color:transparent; 142 } 143 144 #app{ 145 margin: 0 5px; 146 } 147 .nav { 148 height: 45px; 149 width: 100%; 150 background-color: #fff; 151 position: fixed; 152 z-index: 99; 153 opacity: 999; 154 } 155 156 .detail_anchor { 157 display: -webkit-box; 158 display: -webkit-flex; 159 display: flex; 160 height: 44px; 161 line-height: 44px; 162 font-size: 14px; 163 color: #666; 164 box-shadow: 0 1px 6px rgba(0, 0, 0, .1); 165 justify-content: space-evenly; 166 } 167 168 .header-new-title { 169 margin: 0 70px; 170 height: 44px; 171 font-size: 16px; 172 line-height: 44px; 173 text-align: center; 174 color: #333; 175 overflow: hidden; 176 text-overflow: ellipsis; 177 white-space: nowrap; 178 } 179 180 .active { 181 color: #e4393c; 182 } 183 184 .de_btn_bar{ 185 height: 50px; 186 width: 100%; 187 background-color: #fff; 188 position: fixed; 189 z-index: 99; 190 bottom: 0; 191 } 192 .btn_group{ 193 /* display: flex; 194 justify-content: space-evenly; */ 195 height: 100%; 196 } 197 .btn_group_item{ 198 display: inline-block; 199 height: 100%; 200 width: 25%; 201 margin-right: -5px; 202 padding: 0; 203 text-align: center; 204 line-height: 50px; 205 } 206 .add_cart{ 207 color: #fff; 208 background: linear-gradient(138deg,#ffa600,#ffb000 77%,#ffbc00); 209 } 210 .now_buy{ 211 color: #fff; 212 background: linear-gradient(-41deg,#ff4f18,#ff2000 24%,#f10000); 213 } 214 </style> 215 216 </body> 217 218 </html>