一個相似於京東Plus權益介紹的小功能

最近公司要開發一套線上付費的會員App,是和原生一塊兒混合式的開發,有一個會員權益模塊是所有使用H5開發,想給你們看下須要作成的案例:html

clipboard.png

其實沒什麼難點,主要就是功能有:
一、頂部導航欄能夠左右滑動,點擊某一個欄目按鈕內容跟着切換;
二、而且加載一次以後,第二次就從新加載;
三、被點擊的欄目按鈕居中顯示,左右會跟隨點擊的位置滾動
四、手機物理返回按鍵對路由的影響vue

感受本身表達不是特別的清楚,來一張動圖把:git

圖片描述

好了 廢話很少說 開始說代碼相關的東西了:github

頂部導航的實現方案:web

使用 swiper3 實現導航回彈和左右滑動效果vue-router

clipboard.png

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的循環渲染liapp

swiper.js的調用:less

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)
                    }

                })

上面的代碼就能夠實現一、3的要求了 我上傳的代碼不是很全,細節代碼我會附上github地址。移動端web

咱們接下來看第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會一步一步的返回,顯然,這不是咱們要的結果,咱們要的效果應該是「指哪打哪,自我掌控

一、首先,咱們新建一個 global變量 這個用於記錄路由的訪問來源

clipboard.png

二、在對應的路由文件裏面添加路由衛士:

clipboard.png

三、在mounted裏面配置popstate和配置goBack方法:

clipboard.png

四、銷燬組件的時候 移除popstate

clipboard.png

個人三個路由的名稱分別爲:mpos、payPhoneBill、movieTicket,接下來看動圖:

圖片描述

能夠看到 咱們只須要判斷 global.beforeRouteName 和 路由的名稱做爲判斷條件,就能夠作任何操做和交互了,能夠本身很好的控制物理鍵啦!

demo在線預覽:

clipboard.png

demo的代碼地址:https://github.com/yulongwuko...

相關文章
相關標籤/搜索