vue頁面緩存的實現(xiàn)方以及與原生的部分效果對比

前言

作為移動開發(fā)者,相信大家對于使用html開發(fā)的App和使用原生Api開發(fā)的App,或多或少都有所體驗卡儒。他們有各自的優(yōu)勢與劣勢蜜葱,今天我們就參考原生App的效果全景,通過使用vue.js框架來實現(xiàn)一款類似原生效果的應(yīng)用。

項目簡介

聯(lián)華會員線上退貨流程的實現(xiàn)牵囤。主要功能點:選店爸黄、定位、上傳圖片揭鳞、售后查詢炕贵。實現(xiàn)方案:vue.js

效果預(yù)覽

23.gif

項目過程中遇到的難點與解決方案

1、原生的頁面push跳轉(zhuǎn)是一個從右邊往左進入的動畫野崇,pop操作是一個從左往右淡出的動畫称开。下面介紹如何使用vue的Router和transition 來達到這種效果。

  • 所有的頁面都通過vue-router進行管理,給router-view加一個動畫鳖轰。
<transition :name="transitionName">
      <keep-alive>
        <router-view  class="Router"></router-view>
      </keep-alive>
</transition>
  • 如何獲取當前頁面是push操作還是pop操作清酥?監(jiān)聽瀏覽器的popstate 事件。通過在入口文件中監(jiān)聽popstate事件來標記當前的頁面是不是pop操作蕴侣,如果是pop操作就給當前的路由添加一個屬性isBack
window.addEventListener('popstate', function (e) {
  router.isBack = true
}, false)
  • 監(jiān)聽路由的isBack屬性焰轻,給當前頁面設(shè)置push動畫還是pop動畫。至此昆雀,這種動畫效果就實現(xiàn)了辱志。
watch: {
   $route(to, from) {
        // 切換動畫
        let isBack = this.$router.isBack
        if (isBack) {
          this.transitionName = 'slide-left'
        } else {
          this.transitionName = 'slide-right'
        }
        this.$router.isBack = false
   }
}

2、頁面的緩存與銷毀問題
原生的App的push操作會緩存已經(jīng)加載的頁面忆肾,pop操作會銷毀頁面荸频。h5的跳轉(zhuǎn)使用vue-router進行管理,如果不對頁面進行特殊的緩存處理客冈,h5的頁面會在push時銷毀當前頁面旭从,重新創(chuàng)建新頁面,這種體驗明顯的不如原生體驗场仲,下面我們介紹下如何使用vue的頁面緩存機制來達到原生的這種效果和悦。

  • keep-alive是Vue提供的一個抽象組件,用來對組件進行緩存渠缕,從而節(jié)省性能鸽素。他有2個常用屬性include、exclude屬性亦鳞。include屬性表示只有name屬性為xxx的組件會被緩存馍忽,(注意是組件的名字,不是路由的名字)燕差。exclude屬性表示除了name屬性為xxx的組件不會被緩存遭笋,其它組件都會被緩存。這里我們使用include屬性徒探,將push操作的頁面緩存起來瓦呼。

1)第一步:必須設(shè)置頁面的name屬性。

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Main',
      component: Main,
      meta: {
      }
    }
  ]
})

2)第二步:在main.js入口文件中監(jiān)聽router.isBack屬性测暗,判斷是push還是pop央串,如果是push就將頁面的name存到一個數(shù)組中,如果不是就從數(shù)組中移除該頁面碗啄,同時這個數(shù)組我們通過vuex存儲起來质和。這個數(shù)組中存儲的頁面就是我們需要緩存的頁面。

router.beforeEach((to, from, next) => {
  let isBack = router.isBack
  let arr = store.state.keepAlivePages.slice()
  if (isBack) {
    // 從數(shù)組中移除
    let index = arr.indexOf(from.name)
    if (index !== -1) {
      arr.splice(index, 1)
    }
  } else {
    // 加入數(shù)組,push操作都要加入緩存數(shù)組
    let index = arr.indexOf(from.name)
    if (index === -1) {
      arr.push(from.name)
    }
    let indexTo = arr.indexOf(to.name)
    if (indexTo === -1) {
      arr.push(to.name)
    }
  }
  store.commit('SET_KEEPALIVEPAGES', arr)
  next()
})

3) 最后在主頁面中設(shè)置我們需要緩存的頁面

 <transition :name="transitionName">
      <keep-alive :include="keepAlivePages">
        <router-view class="Router"></router-view>
      </keep-alive>
</transition>

3挫掏、如何實現(xiàn)原生界面的側(cè)滑返回效果侦另?

  • 通過判斷手勢的滑動可以實現(xiàn)側(cè)滑返回的效果,但是和原生的側(cè)滑相比還是有一些效果差距的。需要注意的是在主頁面的手勢響應(yīng)可能會影響到滑塊Slider的滑動褒傅,我們可以在通過修飾符@touchmove.stop 阻止手勢的響應(yīng)弃锐,達到不影響Slider的滑動問題。
<template>
  <div id="app" v-on:touchstart="bodyTouchStart" v-on:touchmove="bodyTouchMove" v-on:touchend="bodyTouchEnd">
    <transition :name="transitionName">
      <keep-alive :include="keepAlivePages">
        <router-view class="Router" :style="routerHeightStyle"></router-view>
      </keep-alive>
    </transition>
  </div>
</template>

methods: {
      bodyTouchStart(event) {
        this.touchStartPoint = event.targetTouches[0].pageX
        this.touchStartPointY = event.targetTouches[0].pageY
      },
      bodyTouchMove(event) {
        // 實時計算distance
        this.distance = event.targetTouches[0].pageX - this.touchStartPoint
        this.distanceY = event.targetTouches[0].pageY - this.touchStartPointY
      },
      bodyTouchEnd() {
        // 滾動視圖可能會導(dǎo)致左滑殿托,所以要判斷y方向的距離
        if (this.distance > 100 && Math.abs(this.distanceY) < 50) {
          this.$refs.navigation.clickBack()
        } else {
        }
        this.distance = 0
      }
}

4霹菊、如何實現(xiàn)全局的導(dǎo)航欄?以及導(dǎo)航欄的標題支竹、返回按鈕的顯示等功能旋廷?

  • 在定義路由的時候,我們需要通過meta定義一些可配置的字段礼搁,比如是否顯示導(dǎo)航欄饶碘、導(dǎo)航欄標題、是否顯示返回按鈕馒吴、是否顯示Tabbar等等扎运。
{
    path: '/',
    name: 'Home',
    meta: {
      title: '推薦', // 導(dǎo)航欄標題
      showTabbar: true, // 是否顯示Tabbar
      showBack: false
    },
    component: resolve => require(['../views/home.vue'], resolve)
},
  • 然后在主頁面(一般是App.vue)中設(shè)置導(dǎo)航欄等配置
<template>
  <div id="app" v-on:touchstart="bodyTouchStart" v-on:touchmove="bodyTouchMove" v-on:touchend="bodyTouchEnd">
    <!--nav-->
    <navigation
                ref="navigation"
                v-if="!$route.meta.hiddenNav"
                :title="navTitle"
                :showBack="showBack"
                :background="$route.meta.navBackground"
                :showLine="$route.meta.showLine"></navigation>
    <transition :name="transitionName">
      <keep-alive :include="keepAlivePages">
        <router-view  class="Router" :style="routerHeightStyle"></router-view>
      </keep-alive>
    </transition>
    <tabBar v-show="$route.meta.showTabbar"></tabBar>
  </div>
</template>
  • 需要注意的是,在上面的demo中導(dǎo)航欄的標題取的是一個變量navTitle饮戳,為什么要通過變量取值豪治?是因為有這樣一種場景:比如進入商品詳情頁面,導(dǎo)航欄的標題是服務(wù)器返回的商品名稱扯罐,這種情況頁面已經(jīng)渲染完成负拟,再通過meta設(shè)置標題是沒有效果的。所以目前的方案是用通知的方式歹河,把標題傳遞過來掩浙,然后賦值。
mounted() {
      // 動態(tài)改變詳情頁面的title
      this.bus.$on('changeDetailTitle', (title) => {
        this.$set(this.$route.meta, 'title', title)
        this.navTitle = title
      })
}

綜述

原生App的體驗效果確實優(yōu)于H5秸歧,但是通過以上的各種效果的優(yōu)化涣脚,目前我們的H5項目已經(jīng)能夠更加接近原生的體驗效果,特別是頁面緩存這一塊意義重大寥茫。

最后附上效果圖,大家注意pop后頁面的內(nèi)容哦矾麻,是不是和原生很像.......

24.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末纱耻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子险耀,更是在濱河造成了極大的恐慌弄喘,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件甩牺,死亡現(xiàn)場離奇詭異蘑志,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門急但,熙熙樓的掌柜王于貴愁眉苦臉地迎上來澎媒,“玉大人,你說我怎么就攤上這事波桩〗渑” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵镐躲,是天一觀的道長储玫。 經(jīng)常有香客問我,道長萤皂,這世上最難降的妖魔是什么撒穷? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮裆熙,結(jié)果婚禮上端礼,老公的妹妹穿的比我還像新娘。我一直安慰自己弛车,他們只是感情好齐媒,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著纷跛,像睡著了一般喻括。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贫奠,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天唬血,我揣著相機與錄音,去河邊找鬼唤崭。 笑死拷恨,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的谢肾。 我是一名探鬼主播腕侄,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼芦疏!你這毒婦竟也來了冕杠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤酸茴,失蹤者是張志新(化名)和其女友劉穎分预,沒想到半個月后薪捍,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體笼痹,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡配喳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了凳干。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晴裹。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖纺座,靈堂內(nèi)的尸體忽然破棺而出息拜,到底是詐尸還是另有隱情,我是刑警寧澤净响,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布少欺,位于F島的核電站,受9級特大地震影響馋贤,放射性物質(zhì)發(fā)生泄漏赞别。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一配乓、第九天 我趴在偏房一處隱蔽的房頂上張望仿滔。 院中可真熱鬧,春花似錦犹芹、人聲如沸崎页。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽飒焦。三九已至,卻和暖如春屿笼,著一層夾襖步出監(jiān)牢的瞬間牺荠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工驴一, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留休雌,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓肝断,卻偏偏與公主長得像杈曲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子胸懈,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Z了個L閱讀 291評論 0 4
  • 時光匆匆鱼蝉、轉(zhuǎn)眼第三次大課都過去一周了!作業(yè)一直都是我比較頭疼的箫荡、很多感觸沒辦法表達明白、不過我感受到自己的成長渔隶、感...
    lawyer麗閱讀 215評論 0 0
  • 越過“土坡”羔挡,我還是青年小何 音樂泰斗李宗盛一貫自稱小李洁奈,故斗膽效仿稱為小何。小李之于李宗盛是一種自謙绞灼,但小何之于...
    青年小何閱讀 316評論 0 1
  • 牙周病是口腔最常見的疾病利术,是人類缺牙的主要原因之一。 牙周病是指發(fā)生在牙齒周圍組織的炎癥性疾病低矮,包括牙齦炎和牙周炎...
    牙齒小衛(wèi)士閱讀 604評論 0 0