最近公司要開發一套線上付費的會員App,是和原生一起混合式的開發,有一個會員權益模塊是全部使用H5開發,想給大家看下需要做成的案例:
其實沒什麼難點,主要就是功能有:
1、頂部導航欄可以左右滑動,點擊某一個欄目按鈕內容跟着切換;
2、並且加載一次之後,第二次就重新加載;
3、被點擊的欄目按鈕居中顯示,左右會跟隨點擊的位置滾動
4、手機物理返回按鍵對路由的影響
感覺自己表達不是特別的清楚,來一張動圖把:
好了 廢話不多說 開始說代碼相關的東西了:
頂部導航的實現方案:
使用 swiper3 實現導航回彈和左右滑動效果
html內容::
<div class="rightsProfile">
<div class="rightsProfile_head">
<div id="nav" class="swiper-container">
<ul class="swiper-wrapper">
<li :key="i" v-for="i in myNavBar" :class="{'active-nav':i.active}" class="swiper-slide">
{{i.title}}
</li>
</ul>
</div>
</div>
</div>
我使用了vuejs的循環渲染li
swiper.js的調用:
var myNav = new Swiper('#nav', {
freeMode: true,
freeModeMomentumRatio: 0.5,
slidesPerView: '3',
});
let swiperWidth = myNav.container[0].clientWidth
let maxTranslate = myNav.maxTranslate();
let maxWidth = -maxTranslate + swiperWidth / 2
myNav.on("tap",function(swiper,e){
let slide = swiper.slides[swiper.clickedIndex]
let slideLeft = slide.offsetLeft
let slideWidth = slide.clientWidth
let slideCenter = slideLeft + slideWidth / 2;
// 被點擊slide的中心點
myNav.setWrapperTransition(300)
if (slideCenter < swiperWidth / 2) {
myNav.setWrapperTranslate(0)
} else if (slideCenter > maxWidth) {
myNav.setWrapperTranslate(maxTranslate)
} else {
let nowTlanslate = slideCenter - swiperWidth / 2
myNav.setWrapperTranslate(-nowTlanslate)
}
})
上面的代碼就可以實現1、3的要求了 我上傳的代碼不是很全,細節代碼我會附上github地址。
我們接下來看第2個要求,就是點擊加載一次之後,再次點擊不會重新加載,這裏我使用了vue-router
結構如下:
<template>
<div id="page">
<Loading :isLoading="isLoading"></Loading>
<div class="rightsProfile">
<div class="rightsProfile_head">
<div id="nav" class="swiper-container">
<ul class="swiper-wrapper">
<li :key="i" v-for="i in myNavBar" :class="{'active-nav':i.active}" class="swiper-slide">
{{i.title}}
</li>
</ul>
</div>
</div>
</div>
<keep-alive>
<router-view v-if="$route.meta.keepAlive">
<!-- 這裏是會被緩存的視圖組件,比如 page1,page2 -->
</router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive">
<!-- 這裏是不被緩存的視圖組件,比如 page3 -->
</router-view>
</div>
</template>
<style lang="less">
#nav{
height: 100%;
.swiper-wrapper{
height: 100%;
li{
text-align: center;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
&.active-nav{
color:#fff;
background:#ddd !important;
}
&.active-nav a{
color:#fff;
background:#ddd !important;
}
}
}
}
</style>
<script>
import Loading from "@/components/loading";
export default{
data(){
return{
myNavBar:[{
title:"移動機具",
active:true,
mark:"mpos"
},{
title:"8折話費",
active:false,
mark:"payPhoneBill"
},{
title:"5折看電影",
active:false,
mark:"movieTicket"
},{
title:"家用",
active:false
},{
title:"家用電器",
active:false
},{
title:"家用",
active:false
}],
routerName:""
}
},
components:{
Loading
},
watch: {
$route(to, from) {
// console.log(this.$route.name);
let routerName = this.$route.name;
this.myNavBar.map((el)=>{
el.active = false;
if(el.mark==routerName){
el.active = true;
}
});
}
},
mounted(){
this.$nextTick(()=>{
let that = this;
var myNav = new Swiper('#nav', {
freeMode: true,
freeModeMomentumRatio: 0.5,
slidesPerView: '3',
});
let swiperWidth = myNav.container[0].clientWidth
let maxTranslate = myNav.maxTranslate();
let maxWidth = -maxTranslate + swiperWidth / 2
myNav.on("tap",function(swiper,e){
let slide = swiper.slides[swiper.clickedIndex]
let slideLeft = slide.offsetLeft
let slideWidth = slide.clientWidth
let slideCenter = slideLeft + slideWidth / 2;
// 被點擊slide的中心點
myNav.setWrapperTransition(300)
if (slideCenter < swiperWidth / 2) {
myNav.setWrapperTranslate(0)
} else if (slideCenter > maxWidth) {
myNav.setWrapperTranslate(maxTranslate)
} else {
let nowTlanslate = slideCenter - swiperWidth / 2
myNav.setWrapperTranslate(-nowTlanslate)
}
that.myNavBar.map((el)=>{
el.active = false;
});
that.myNavBar[swiper.clickedIndex].active = true;
that.$router.push({
path:that.myNavBar[swiper.clickedIndex].mark
})
})
})
}
}
</script>
頭部導航在主路由裏面,router-view顯示每個欄目對應的內容,可以給每個路由設置keep-alive,實現條件3。
從事移動端web開發的小夥伴們應該對手機的物理返回鍵“深惡痛絕”把,同樣我們做完了上面那個demo,當你點擊安卓的物理返回鍵的時候,demo會一步一步的返回,顯然,這不是我們要的結果,我們要的效果應該是“指哪打哪,自我掌控”
1、首先,我們新建一個 global變量 這個用於記錄路由的訪問來源
2、在對應的路由文件裏面添加路由衛士:
3、在mounted裏面配置popstate和配置goBack方法:
4、銷燬組件的時候 移除popstate
我的三個路由的名稱分別爲:mpos、payPhoneBill、movieTicket,接下來看動圖:
可以看到 我們只需要判斷 global.beforeRouteName 和 路由的名稱作爲判斷條件,就可以做任何操作和交互了,可以自己很好的控制物理鍵啦!
demo在線預覽:
demo的代碼地址:https://github.com/yulongwuko...