详解vue 在移动端体验上的优化解决方案


Posted in Javascript onMay 20, 2019

去年年底自己搭了一个vue在移动端的开发框架,感觉体验不是很好。上个星期又要做移动端的项目了。所以我花了两天时间对之前的那个开发框架做了以下优化

  • 自定义vuex-plugins-loading
  • 路由切换动画 + keep alive 动态管理缓存组件
  • better-scroll与vue的最佳实践(better-scroll的vue化)
  • 自定义指令(vue-finger:包括点击,长按,双击,拖拽移动,多点触控,滑动,旋转,缩放手势)
  • 移动端适配方案
  • 如何分情况处理页面置顶
  • 路由懒加载

自定义 vuex-plugins-loading

如果每个页面在数据加载完成前,展示loading。你首先想到的是每个页面设置状态,show和hide状态。但是这样冗余代码太多了,而且自己写的都烦。我之前的react的项目中用到了dva,其中有dva-loading库,之前就有研究过,所以我就用他的思想,自己写一个vuex-loading。

实现思路:vuex中注册一个管理loading的module,通过绑定异步的action,将每个action的loading存在vuex中,这样我在每个页面只需要在vuex的store中拿相对应的action loading就能达到此目的

## 核心代码
  store.subscribeAction({
   before: action => {
    if (shouldEffect(action, includes, excludes)) {
     store.commit({ type: namespace + '/SHOW', payload: action.type })
    }
   },
   after: action => {
    if (shouldEffect(action, includes, excludes)) {
     store.commit({ type: namespace + '/HIDE', payload: action.type })
    }
   }
  })
 }
}

使用之前大家可以先了解一下subscribeAction

想安装此插件,请点击这里,记得给个star哟

注意: 使用上述代码,vuex必需为3.1.0版本。因为subscribeAction在3.1.0才新增的

路由切换动画 + keep alive 动态管理缓存组件

之前采用的是全局设置路由切换动画,但是体验效果不是很好,特别是返回列表页,页面会引起回弹,页面切换时会有暂时的空白。

未改造前的,也是参考别人的做法

## app.vue
 <transition :name="transitionName"> 
  <keep-alive :include="data">
    <router-view></router-view>
  </keep-alive>
 </transition>
 
 computed: {
  // 数据存放在vuex里面
  ...mapState({
   data: state => {
    return state.global.data
   }
  })
 },
 methods: {
  // 设置Keep_alive路由
  setKeep_alive (to) {
   if (to.meta.keepAlive) {
    this.$store.dispatch({
     type: 'global/setData',
     payload: to.name
    })
   }
  }
 },
 watch: {
  '$route' (to, from) {
   // 此时从from页面跳转到to页面
   this.setKeep_alive(to)
   const routeDeep = ['/', '/list', '/detail', '/reservation', '/addCars']
   const toDepth = routeDeep.indexOf(to.path)
   const fromDepth = routeDeep.indexOf(from.path)
   if (!from.name) {
    this.transitionName = 'fold'
    return
   }
   this.transitionName = toDepth > fromDepth ? 'fold-left' : 'fold-right'
  }
 },
## router.js
scrollBehavior (to, from, savedPosition) {
  // keep-alive 返回缓存页面后记录浏览位置
  if (savedPosition && to.meta.keepAlive) {
   return savedPosition
  }
  // 异步滚动操作
  return new Promise((resolve) => {
   setTimeout(() => {
    resolve({ x: 0, y: 1 })
   }, 0)
  })
 },

两个问题

列表页滑动到一定位置后跳转到详情页,返回列表页页面回弹

原因:原生滚动条的位置是不变的,使用scrollBehavior,根据上述代码可知滚动条会有一个闪烁的过程先置顶,然后滚动到上次保留的位置。

页面切换时会有暂时的空白,过渡不正常。

改造后

## app.vue
<keep-alive :include="data">
 <router-view></router-view>
</keep-alive>
computed: {
  // 数据存放在vuex里面
  ...mapState({
   data: state => {
    return state.global.data
   }
  })
 },
 methods: {
  // 设置Keep_alive路由
  setKeep_alive (to) {
   if (to.meta.keepAlive) {
    this.$store.dispatch({
     type: 'global/setData',
     payload: to.name
    })
   }
  }
 },
 watch: {
  '$route' (to, from) {
   // 此时从from页面跳转到to页面
   this.setKeep_alive(to)
  }
 },

list.vue

<Scroll
 ref="scroll"
 class="scroll-home"
 :scrollbar="scrollbar"
 :probeType="3"
 :pullDownRefresh="pullDownRefresh"
 :pullUpLoad="true"
 @pullingDown="onRefresh"
 @scroll="scroll"
 @pullingUp="onLoad"
>
 <div class="contantView">
 </div>
</Scroll>

1.采用better-scroll后,第一个问题可以直接解决。而且不用设置scrollBehavior,不懂可以去看better-scroll

2.给页面CSS添加设置“position:absolute;”,此时页面脱离文档流,不占空间,这样就不会把下一页挤下去,完成平滑过渡。使用better-scroll给页面CSS添加设置“position:fixed;”。

如果页面布局里面有用到flex布局,一定要给flex组件加一个position为absolute或者fixed的div。

上述代码中已有keep alive 动态管理缓存路由的思路。

better-scroll与vue的最佳实践

之前在一篇文章上看到BetterScroll可能是目前最好用的移动端滚动插件,所以这次就想试试,滴滴开源的cube-ui组件库里面大多数用到的滑动组件都是基于better-scroll,体验了一下感觉还挺好。为什么没有用cube了?因为个人感觉主题颜色有点丑。所以自己就打算基于better-scroll封装一个vue版本的scroll组件。不说那么多了,立马上图:

详解vue 在移动端体验上的优化解决方案

想用better-scroll还有另外一个原因,我想自定义上下拉的动画。

想看demo及源码请点击这里。记得给个star哟

自定义指令 vue-finger

包括点击,长按,双击,拖拽移动,多点触控,滑动,旋转,缩放手势

这一块我这边是基于别人的demo改造的,在这些指令里面你可以做很多在移动端手势方面想做的事情。后续我会继续迭代这些指令,制定出体验接近原生的组件,大家要关注我的github哟

移动端适配方案

## rem.js
const baseSize = 32
// 设置 rem 函数
function setRem () {
 // 当前页面宽度相对于 750 宽的缩放比例,可根据自己需要修改。
 const scale = document.documentElement.clientWidth / 750
 // 设置页面根节点字体大小
 document.documentElement.style.fontSize = (baseSize * Math.min(scale, 2)) + 'px'
}
// 初始化
setRem()
// 改变窗口大小时重新设置 rem
window.onresize = function () {
 setRem()
}
## main.js
import './rem'

还有最后还有一步。对于经常写样式的同学,px转rem是不是感觉很烦。 我这边处理的方式是,在项目根目录新建一个postcss.config.js文件。这样你只需按照设计稿的样式,正常写px就好。运行项目时会自动帮你转成rem。

module.exports = {
 plugins: {
  'autoprefixer': {
   browsers: ['Android >= 4.0', 'iOS >= 7']
  },
  'postcss-pxtorem': {
   rootValue: 16,
   propList: ['*']
  }
 }
}

如何分情况处理页面置顶

上文有讲到vue-router里面scrollBehavior这个方法。

## router.js
scrollBehavior (to, from, savedPosition) {
  // keep-alive 返回缓存页面后记录浏览位置
  if (savedPosition && to.meta.keepAlive) {
   return savedPosition
  }
  // 异步滚动操作
  return new Promise((resolve) => {
   setTimeout(() => {
    resolve({ x: 0, y: 1 })
   }, 0)
  })
 },

但是感觉添加页面转场动画后。页面会有回弹。所以我就放弃它了。不添加动画的可以考虑。

我这边用到了better-scroll后就不用担心这个问题。看完better-scroll文档介绍,你就会发现better-scroll就是为移动端运用而生的。

路由懒加载

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。 这是路由懒加载就很重要了。看过官方文档大家应该都会用了,这里我就不介绍了。

// 路由懒加载
const _import_ = file => () => import('./views/' + file + '.vue')

routes: [
  {
   path: '/',
   name: 'home',
   component: _import_('Home/Home'),
   meta: {
    title: '首页',
    keepAlive: true
   }
  },
]

终于写完了,以上这些就是我在移动端体验优化的实战。希望能帮到大家。如果往后有什么好的优化方案我会继续更新。谢谢大家的观看。觉得好的点个赞

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript的函数
Jan 31 Javascript
js实现键盘操作实现div的移动或改变的原理及代码
Jun 23 Javascript
JavaScript截取字符串的2个函数介绍
Aug 27 Javascript
js实现ifram取父窗口URL地址的方法
Feb 09 Javascript
JS实现网页上随滚动条滚动的层效果代码
Nov 04 Javascript
JS和jQuery使用submit方法无法提交表单的原因分析及解决办法
May 17 Javascript
关于JavaScript中的this指向问题总结篇
Jul 23 Javascript
浅析webpack 如何优雅的使用tree-shaking(摇树优化)
Aug 16 Javascript
webpack学习教程之前端性能优化总结
Dec 05 Javascript
jQuery幻灯片插件owlcarousel参数说明中文文档
Feb 27 jQuery
axios 封装上传文件的请求方法
Sep 26 Javascript
详解Vue中的scoped及穿透方法
Apr 18 Javascript
vue-i18n结合Element-ui的配置方法
May 20 #Javascript
JS实现选项卡效果的代码实例
May 20 #Javascript
微信打开网址添加在浏览器中打开提示的办法
May 20 #Javascript
浅谈Vuex注入Vue生命周期的过程
May 20 #Javascript
微信小程序图表插件wx-charts用法实例详解
May 20 #Javascript
Nuxt项目支持eslint+pritter+typescript的实现
May 20 #Javascript
vue3.0 搭建项目总结(详细步骤)
May 20 #Javascript
You might like
PHP4 与 MySQL 数据库操作函数详解
2006/10/09 PHP
destoon出现验证码不显示时的紧急处理方法
2014/08/22 PHP
PHP框架Laravel学习心得体会
2015/10/28 PHP
php flush无效,IIS7下php实时输出的方法
2016/08/25 PHP
类之Prototype.js学习
2007/06/13 Javascript
js中的eventType事件及其浏览器支持性介绍
2013/11/29 Javascript
javascript修改IMG标签的src问题
2014/03/28 Javascript
js表头排序实现方法
2015/01/16 Javascript
JS中使用apply、bind实现为函数或者类传入动态个数的参数
2016/04/26 Javascript
用JS动态改变表单form里的action值属性的两种方法
2016/05/25 Javascript
详解vue-router 2.0 常用基础知识点之router.push()
2017/05/10 Javascript
MVVM 双向绑定的实现代码
2018/06/21 Javascript
vue 之 css module的使用方法
2018/12/04 Javascript
js中对象和面向对象与Json介绍
2019/01/21 Javascript
Layui之table中的radio在切换分页时无法记住选中状态的解决方法
2019/09/02 Javascript
基于ant design日期控件使用_仅月份的操作
2020/10/27 Javascript
js数组的基本使用总结
2021/01/18 Javascript
[43:26]完美世界DOTA2联赛PWL S2 Forest vs Rebirth 第二场 11.20
2020/11/23 DOTA
Pyhton中防止SQL注入的方法
2015/02/05 Python
Python中用字符串调用函数或方法示例代码
2017/08/04 Python
PHP实现发送和接收JSON请求
2018/06/07 Python
python+PyQT实现系统桌面时钟
2020/06/16 Python
几个适合python初学者的简单小程序,看完受益匪浅!(推荐)
2019/04/16 Python
python命令行参数用法实例分析
2019/06/25 Python
windows环境中利用celery实现简单任务队列过程解析
2019/11/29 Python
python统计字符的个数代码实例
2020/02/07 Python
python生成并处理uuid的实现方式
2020/03/03 Python
华为旗下电子商务平台:华为商城
2016/08/06 全球购物
LEGO玩具英国官方商店:LEGO Shop GB
2018/03/27 全球购物
金融专业个人求职信
2013/09/22 职场文书
学生思想表现的评语
2014/01/30 职场文书
劳资员岗位职责
2015/02/13 职场文书
高一化学教学反思
2016/02/22 职场文书
手把手教你用SpringBoot将文件打包成zip存放或导出
2021/06/11 Java/Android
CSS作用域(样式分割)的使用汇总
2021/11/07 HTML / CSS
古见同学有交流障碍症 第二季宣传CM公开播出
2022/04/11 日漫