详解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 相关文章推荐
ie8 不支持new Date(2012-11-10)问题的解决方法
Jul 31 Javascript
JS获取当前网址、主机地址项目根路径
Nov 19 Javascript
谈谈encodeURI和encodeURIComponent以及escape的区别与应用
Nov 24 Javascript
JavaScript拖拽、碰撞、重力及弹性运动实例分析
Jan 08 Javascript
Bootstrap入门书籍之(五)导航条、分页导航
Feb 17 Javascript
详解angular2采用自定义指令(Directive)方式加载jquery插件
Feb 09 Javascript
jQuery 开发之EasyUI 添加数据的实例
Sep 26 jQuery
Cocos2d实现刮刮卡效果
Dec 20 Javascript
vue中利用simplemde实现markdown编辑器(增加图片上传功能)
Apr 29 Javascript
js图片无缝滚动插件使用详解
May 26 Javascript
jQuery 淡入/淡出效果函数用法分析
May 19 jQuery
基于JavaScript实现年月日三级联动
Jun 22 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
php代码优化及php相关问题总结
2006/10/09 PHP
基于HTTP长连接的&quot;服务器推&quot;技术的php 简易聊天室
2009/10/31 PHP
ThinkPHP空模块和空操作详解
2014/06/30 PHP
PHP生成不重复标识符的方法
2014/11/21 PHP
PHP实现加强版加密解密类实例
2015/07/29 PHP
php 算法之实现相对路径的实例
2017/10/17 PHP
PHP分享图片的生成方法
2018/04/25 PHP
php layui实现前端多图上传实例
2019/07/30 PHP
制作特殊字的脚本
2006/06/26 Javascript
jquery中动态效果小结
2010/12/16 Javascript
jQuery结合PHP+MySQL实现二级联动下拉列表[实例]
2011/11/15 Javascript
jQuery中scrollLeft()方法用法实例
2015/01/16 Javascript
PHP+mysql+Highcharts生成饼状图
2015/05/04 Javascript
JavaScript类型系统之基本数据类型与包装类型
2016/01/06 Javascript
JS中移除非数字最多保留一位小数
2018/05/09 Javascript
js限制输入框只能输入数字(onkeyup触发)
2018/09/28 Javascript
3分钟读懂移动端rem使用方法(推荐)
2019/05/06 Javascript
python 多进程通信模块的简单实现
2014/02/20 Python
Python ORM框架SQLAlchemy学习笔记之映射类使用实例和Session会话介绍
2014/06/10 Python
Python Web编程之WSGI协议简介
2018/07/18 Python
Django rest framework工具包简单用法示例
2018/07/20 Python
Flask框架学习笔记之消息提示与异常处理操作详解
2019/08/15 Python
Python Web框架之Django框架文件上传功能详解
2019/08/16 Python
Django 框架模型操作入门教程
2019/11/05 Python
Python持续监听文件变化代码实例
2020/07/22 Python
Python importlib模块重载使用方法详解
2020/10/13 Python
UGG澳洲官网:UGG Australia
2018/04/26 全球购物
构造方法和其他方法的区别
2016/04/26 面试题
opencv实现图像几何变换
2021/03/24 Python
水产养殖学应届生求职信
2013/09/29 职场文书
旅游与酒店管理的自我评价分享
2013/11/03 职场文书
办公室前台岗位职责范本
2013/12/10 职场文书
会计电算化专业毕业生自荐信
2013/12/20 职场文书
向领导表决心的话
2014/03/11 职场文书
一年级小学生评语大全
2014/12/25 职场文书
小学英语新课改心得体会
2016/01/22 职场文书