详解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 相关文章推荐
图片完美缩放
Sep 07 Javascript
百度 popup.js 完美修正版非常的不错 脚本之家推荐
Apr 17 Javascript
Script标签与访问HTML页面详解
Jan 10 Javascript
如何用jquery控制表格奇偶行及活动行颜色
Apr 20 Javascript
AngularJS 模型详细介绍及实例代码
Jul 27 Javascript
Mac系统下Webstorm快捷键整理大全
May 28 Javascript
利用node.js实现反向代理的方法详解
Jul 24 Javascript
关于定制FileField中的上传文件名称问题
Aug 22 Javascript
分析JS中this引发的bug
Dec 12 Javascript
JavaScript实现预览本地上传图片功能完整示例
Mar 08 Javascript
jQuery属性选择器用法实例分析
Jun 28 jQuery
JavaScript 斐波那契数列 倒序输出 输出100以内的质数代码实例
Sep 11 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
成本8450万,票房仅2亿,口碑两极分化,又一部DC电影扑街了
2020/04/09 欧美动漫
深入解析php中的foreach函数
2013/08/31 PHP
php判断数组元素中是否存在某个字符串的方法
2014/06/14 PHP
php_imagick实现图片剪切、旋转、锐化、减色或增加特效的方法
2014/12/15 PHP
基于ThinkPHP5.0实现图片上传插件
2017/09/25 PHP
CentOS7编译安装php7.1的教程详解
2019/04/18 PHP
PHP设计模式(五)适配器模式Adapter实例详解【结构型】
2020/05/02 PHP
JS解密入门 最终变量劫持
2008/06/25 Javascript
关于B/S判断浏览器断开的问题讨论
2008/10/29 Javascript
jQuery对表单的操作代码集合
2011/04/06 Javascript
使用JavaScript实现Java的List功能(实例讲解)
2013/11/07 Javascript
JQuery验证jsp页面属性是否为空(实例代码)
2013/11/08 Javascript
firefox下jquery ajax返回object XMLDocument处理方法
2014/01/26 Javascript
谈谈我对JavaScript DOM事件的理解
2015/12/18 Javascript
浅谈nodejs中的类定义和继承的套路
2017/07/26 NodeJs
认识jQuery的Promise的具体使用方法
2017/10/10 jQuery
NodeJS 实现多语言的示例代码
2018/09/11 NodeJs
在vue中使用echarts图表实例代码详解
2018/10/22 Javascript
ionic使用angularjs表单验证(模板验证)
2018/12/12 Javascript
JavaScript实现PC端四格密码输入框功能
2020/02/19 Javascript
详解JavaScript 高阶函数
2020/09/14 Javascript
[01:14:12]2018DOTA2亚洲邀请赛4.7 总决赛 LGD vs Mineski 第二场
2018/04/09 DOTA
操作Windows注册表的简单的Python程序制作教程
2015/04/07 Python
python判断字符串是否是json格式方法分享
2017/11/07 Python
python3利用venv配置虚拟环境及过程中的小问题小结
2018/08/01 Python
深入浅析python 协程与go协程的区别
2019/05/09 Python
keras分类模型中的输入数据与标签的维度实例
2020/07/03 Python
Foreo国际站:Foreo International
2018/10/29 全球购物
英国领先的豪华时尚家居网上商店:Amara
2019/08/12 全球购物
四风问题自查报告剖析材料
2014/02/08 职场文书
《赠汪伦》教学反思
2014/04/12 职场文书
2014年环境卫生工作总结
2014/11/24 职场文书
2015社区个人工作总结范文
2015/05/13 职场文书
JS中一些高效的魔法运算符总结
2021/05/06 Javascript
MySQL 8.0 之不可见列的基本操作
2021/05/20 MySQL
Mybatis是这样防止sql注入的
2021/12/06 Java/Android