Vue仿京东移动端web版商品详情页滚动样式
要求:
- 页面顶部固定有 商品、评价、、推荐详情四个选项卡,对应四个部分的内容。
- 商品:显示轮播图、标题、价格等;评价:显示4条精选评价;推荐:显示两行三列6条推荐信息;详情:商品的详细介绍通常为富文本或一系列图片。
- 点任意选项卡会切换样式且滚动到对应的内容位置,
- 手动滚动页面,导航选项栏同样会自动切换对应样式。
- 当页面滚动距离为0时,导航选项栏透明度为0,且不可点击,每往下滚动20增加0.1,大于等于200时一直为1。(考虑性能可改为无级自动透明度或者每40增加0.2)
- 点击导航栏商品选项卡时时,滚动到0且透明度直接为0,
绑定滚动事件
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(){ ocument.documentElement.scrollTop = this.$refs.comment.offsetTop - 45; },
完整代码
样式细节未打磨,部分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" > 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" > 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" > 56 </div> 57 </div> 58 59 60 61 </div> 62 <script> 63 var vm = new Vue({ 64 el: ‘#app‘, 65 data: { 66 scrollTop: 0, 67 opacity: 0, 68 active: ‘goods‘, 69 70 }, 71 // 绑定滚动事件 72 mounted() { 73 window.addEventListener(‘scroll‘, this.handleScroll); 74 }, 75 methods: { 76 // 监听页面滚动 77 handleScroll() { 78 // 获取当前的滚动距离 79 var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop 80 //console.log(scrollTop) 81 82 if (scrollTop < 200) { 83 // 当滚动距离小于200时,计算导航透明度,可以考虑修改为每20增加0.1 84 // this.opacity = (scrollTop / 200).toFixed(1); 85 this.opacity = scrollTop / 200; 86 this.active = ‘goods‘; 87 return 88 } else { 89 this.opacity = 1 90 } 91 // 当滚动距离不小于200时,获取三个部分的顶部位置-45。 92 let commentTop = this.$refs.comment.offsetTop - 45; 93 let recommendTop = this.$refs.recommend.offsetTop - 45; 94 let detailTop = this.$refs.detail.offsetTop - 45; 95 // 计算滚动距离在哪个区间,修改this.active对应的样式名 96 if (scrollTop < commentTop) { if (this.active != ‘goods‘) this.active = ‘goods‘; } 97 else if (scrollTop >= commentTop && scrollTop < recommendTop) { if (this.active != ‘comment‘) this.active = ‘comment‘; } 98 else if (scrollTop >= recommendTop && scrollTop < detailTop) { if (this.active != ‘recommend‘) this.active = ‘recommend‘; } 99 else if (scrollTop >= detailTop) { if (this.active != ‘detail‘) this.active = ‘detail‘; } 100 }, 101 // 点击导航栏第一个商品选项卡时,直接滚动到0 102 onScrollGoods() { 103 document.documentElement.scrollTop = 0; 104 }, 105 // 点击导航栏其他选项卡时,直接滚动到对应ref的offsetTop-45(导航栏高度) 106 onScrollComment() { 107 if (!this.opacity) return; 108 document.documentElement.scrollTop = this.$refs.comment.offsetTop - 45; 109 }, 110 onScrollRecommend() { 111 if (!this.opacity) return; 112 document.documentElement.scrollTop = this.$refs.recommend.offsetTop - 45; 113 }, 114 onScrollDetail() { 115 if (!this.opacity) return; 116 document.documentElement.scrollTop = this.$refs.detail.offsetTop - 45; 117 }, 118 }, 119 }) 120 </script> 121 <style lang="less"> 122 body { 123 margin: 0; 124 } 125 a { 126 text-decoration: none; 127 color: #2c3e50; 128 } 129 #app{ 130 margin: 0 5px; 131 } 132 .nav { 133 height: 45px; 134 width: 100%; 135 background-color: #fff; 136 position: fixed; 137 border-bottom: 45px; 138 z-index: 99; 139 opacity: 999; 140 } 141 142 .detail_anchor { 143 display: -webkit-box; 144 display: -webkit-flex; 145 display: flex; 146 height: 44px; 147 line-height: 44px; 148 font-size: 14px; 149 color: #666; 150 box-shadow: 0 1px 6px rgba(0, 0, 0, .1); 151 justify-content: space-evenly; 152 } 153 154 .header-new-title { 155 margin: 0 70px; 156 height: 44px; 157 font-size: 16px; 158 line-height: 44px; 159 text-align: center; 160 color: #333; 161 overflow: hidden; 162 text-overflow: ellipsis; 163 white-space: nowrap; 164 } 165 166 .active { 167 color: #e4393c; 168 } 169 </style> 170 171 </body> 172 173 </html>