vue页面缓存的实现方以及与原生的部分效果对比

2019-04-17  本文已影响0人  Darren151666

前言

作为移动开发者,相信大家对于使用html开发的App和使用原生Api开发的App,或多或少都有所体验。他们有各自的优势与劣势,今天我们就参考原生App的效果,通过使用vue.js框架来实现一款类似原生效果的应用。

项目简介

联华会员线上退货流程的实现。主要功能点:选店、定位、上传图片、售后查询。实现方案:vue.js

效果预览

23.gif

项目过程中遇到的难点与解决方案

1、原生的页面push跳转是一个从右边往左进入的动画,pop操作是一个从左往右淡出的动画。下面介绍如何使用vue的Router和transition 来达到这种效果。

<transition :name="transitionName">
      <keep-alive>
        <router-view  class="Router"></router-view>
      </keep-alive>
</transition>
window.addEventListener('popstate', function (e) {
  router.isBack = true
}, false)
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操作会缓存已经加载的页面,pop操作会销毁页面。h5的跳转使用vue-router进行管理,如果不对页面进行特殊的缓存处理,h5的页面会在push时销毁当前页面,重新创建新页面,这种体验明显的不如原生体验,下面我们介绍下如何使用vue的页面缓存机制来达到原生的这种效果。

1)第一步:必须设置页面的name属性。

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

2)第二步:在main.js入口文件中监听router.isBack属性,判断是push还是pop,如果是push就将页面的name存到一个数组中,如果不是就从数组中移除该页面,同时这个数组我们通过vuex存储起来。这个数组中存储的页面就是我们需要缓存的页面。

router.beforeEach((to, from, next) => {
  let isBack = router.isBack
  let arr = store.state.keepAlivePages.slice()
  if (isBack) {
    // 从数组中移除
    let index = arr.indexOf(from.name)
    if (index !== -1) {
      arr.splice(index, 1)
    }
  } else {
    // 加入数组,push操作都要加入缓存数组
    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) 最后在主页面中设置我们需要缓存的页面

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

3、如何实现原生界面的侧滑返回效果?

<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() {
        // 滚动视图可能会导致左滑,所以要判断y方向的距离
        if (this.distance > 100 && Math.abs(this.distanceY) < 50) {
          this.$refs.navigation.clickBack()
        } else {
        }
        this.distance = 0
      }
}

4、如何实现全局的导航栏?以及导航栏的标题、返回按钮的显示等功能?

{
    path: '/',
    name: 'Home',
    meta: {
      title: '推荐', // 导航栏标题
      showTabbar: true, // 是否显示Tabbar
      showBack: false
    },
    component: resolve => require(['../views/home.vue'], resolve)
},
<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>
mounted() {
      // 动态改变详情页面的title
      this.bus.$on('changeDetailTitle', (title) => {
        this.$set(this.$route.meta, 'title', title)
        this.navTitle = title
      })
}

综述

原生App的体验效果确实优于H5,但是通过以上的各种效果的优化,目前我们的H5项目已经能够更加接近原生的体验效果,特别是页面缓存这一块意义重大。

最后附上效果图,大家注意pop后页面的内容哦,是不是和原生很像.......

24.gif
上一篇下一篇

猜你喜欢

热点阅读