记 vue 移动端开发 中的经验

栏目: JavaScript · 发布时间: 5年前

内容简介:手上的 vue移动端 项目已经开发了大几个月了,遇到了一些很有意思的坑,也让自己学习了很多;写此文主要目的是记下一些我遇到的坑,以及自己的解决方案,分享的同时也方便以后复习。项目的底层是上司通过 Cordova 等常用的 hybird app工具打包出来的。然后通过 webview 打开我的vue项目。所以严格意义上说,我还是在做单页面应用。 hybird app 的底层会提供一些api 给我调用,方便我关闭打开webview,或者跳转到不同子页面。hybird app会集成不同的业务。这些业务有hybir

项目背景

手上的 vue移动端 项目已经开发了大几个月了,遇到了一些很有意思的坑,也让自己学习了很多;写此文主要目的是记下一些我遇到的坑,以及自己的解决方案,分享的同时也方便以后复习。

项目的底层是上司通过 Cordova 等常用的 hybird app工具打包出来的。然后通过 webview 打开我的vue项目。所以严格意义上说,我还是在做单页面应用。 hybird app 的底层会提供一些api 给我调用,方便我关闭打开webview,或者跳转到不同子页面。hybird app会集成不同的业务。这些业务有hybird app本事的服务,也有像我这种,完全来自其服务的页面。这些就是项目大概的背景。

上中下三部分的定位问题。

这个问题我在文章 中已经详细说过。

rem 的使用;

我直接在 app.vue 中添加以下方法,运行后,你会在html 标签中看到 fontsize 设置为了50px; 表示 1rem = 50px;

created() {
      this.resize(document, window);
    },
    
methods:{
    /*设置rem参照单位。width:1rem = 50px 所以设计稿宽 375px == 375/50 = 7.5rem
      * 由于页面中有些元素用了绝对定位。特别是top,bottom。由于设备不同,计算出的rem不同,
      * 导致定位覆盖。所以,建议涉及高度的 统一用 px 做单位,包括padding-top,bottom等。
      * 因为高度存在滚动条,不存在适配问题。主要针对宽度做适配。
      *
      * */
      resize(doc, win) {
        var docE1 = doc.documentElement,
          resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
          recalc = function () {
            var clientWidth = docE1.clientWidth;
            if (!clientWidth) return;
            //docE1.style.fontSize = clientWidth / 375  + 'px'; 这里希望设置 1rem = 1px,实验证明,这样做 会导致 html 的 fontsize小于 12px
            docE1.style.fontSize = (clientWidth / (375*2)) * 100 + 'px'; //乘以100的意义是,1为了不受fontsize小于12的影响,2为了计算方便;
          };
        if (!doc.addEventListener) return;
        win.addEventListener(resizeEvt, recalc, false);
        doc.addEventListener('DOMContentLoaded', recalc, false);
      },
}

记 vue 移动端开发 中的经验

使用建议:

1,少量大小的定义尽量使用px,因为对自适应效果影响不大。例如某个div的padding,设置为5px 10px,影响是不大的。

2,宽度上的定义尽量使用rem 作为单位,因为移动设备对宽度敏感,可谓寸金寸土。设置了以上代码后,可以通过设计稿尺寸/50 得到rem单位的数值。 例如 padding:10px; 可以写成 padding: 10px 0.2rem; 或者 padding:0.2rem;

3,高度上的定义,尽量使用px;因为本项目可以滚动内容页,所以高度是不敏感的。设置为px 的原因是,后面定位 loadermore 组件会有帮助。当然,如果你对计算很有把握,或者页面内容不允许滚动,也可以使用 rem;

刷新某个子页面

遇到一个填写表单点保存形成草稿模式的需求。要求在url中加入参数 id;刷新本页面,重新通过id获取数据回填。 vue 是单页面应用,肯定不能全局刷新。

同事的解决方案

调用保存接口,获取到id后, 通过

this.router.push(this.$route.path + "&id=" + id);//加参数本页并不会刷新

改变url ,然后重新申请 调用接口,拿到最新的数据,回填回去。

这样做,理论上是行得通的。当时很危险,因为用户操作页面,会改变很多变量。如果回填数据后,由于没有经历完整的created等生命周期,这些变量还是原来状态,容易出bug;

其次,如果像本项目那样,需要支持 hybird app 通过url+id 的方式直接去到草稿的话,代码不好维护。所以,最理想的做法,就是真实的重新

load 一次这个子页面。

正确做法

利用vue 的provide / inject api

* app.vue 中定义
 <router-view v-if="isRouterAlive"/>
data() {
      return {
        isRouterAlive: true,
      }
    },
 provide() {
      return {
        reload: this.reload,
      }
    },
methods: {
    reload() {
        this.isRouterAlive = false
        this.$nextTick(() => (this.isRouterAlive = true))
      },
    }


* 需要刷新的子页面
inject: ['reload'],

//需要调用的地方
let path =  this.$route.path+"?id="+id
this.$router.replace(path);
this.reload();

keep-alive 页面怎么刷新

这个需求很常见,有个列表页面,点击某一条去到详情页面,点击返回,列表页面保持状态不变,滚动条保持原来位置。如果,详情对数据做了改变,点击返回,列表页面才刷新。

* app.vue 中
<div id="app">
    <keep-alive>
      <router-view v-if="isRouterAlive&&$route.meta.keepAlive"/>
    </keep-alive>
    <router-view v-if="isRouterAlive&&!$route.meta.keepAlive"/>
  </div>

* route.js 中
{
      path: 'a',//我的草稿
      name: 'myDraft',
      meta:{
        keepAlive:true,
      },
      component: resolve => require(['page/myDraft'],resolve)
    },

这样,定义了meta keepAlive 为true 的页面就会被 缓存。数据不变的情况下,点击返回, 只要把滚动条位置设置到原来离开哪里就好了。

但是问题来了,1,从首页进入 keepAlive 页面,每次都要刷新,二,详情页如果改变了数据,返回后也要刷新 页面。

这里我主要通过 eventBus 来解决了组件通知 页面 刷新的问题。

细节可以看我的笔记,最好的实践应该是最后提到大神的链接文章。

不同页面跳转到同一个页面,topBar 点击返回,回到各个出发位置。

* topBar.vue 
组件的封装并不难,就是预留自定cancel函数,不然就调用 app.vue 中的 backHome 函数 对返回做统一处理
inject:['backHome'],
 cancel(){
        if(this.popup){ 
          this.$emit('cancel')
        }else{
          this.backHome();
        }
      },
      
* app.vue

provide() {
      return {
        backHome:this.backHome
      }
    },
backHome(){ //返回或退出webview
        let  isOutsidePage = this.$route.params.inside;
        let  from = this.$route.params.from;
        if(isOutsidePage=='in'){ //内页跳转
          if(from=="CC"){ //回到a中心
            this.$router.replace('/controlCenter')
          }else if(from=="SF"){ //回到b中心
            this.$router.replace('/controlCenter2')
          }else { //回到原来的子页面(从a页到b页前,必须要先保存lastFullPath)
            this.$router.replace(this.$store.getters.lastFullPath)
            this.$store.commit('setLastFullPath',"")//置空旧路径
          }
        }else{//关闭webView
            closeWebView();
        }
      }
      
* router.js
{
      path: '/myDraft/:from/:inside',
      name: 'myDraft',
      component: resolve => require(['page/myDraft'],resolve)
    },
    {
      path: '/myDraft', 
      redirect: 'myDraft/ll/out',
    },

通过上面的定义 //hybrid app 只需要调用 ip:xxxx/myDraft 就能打开这个页面,并且返回键自动关闭webview;

通过 CC CF 等标志字符 可以判断来自哪个 中心的。

最后来到重点的 子页跳子页返回 操作,主要就是需要借助vuex 保存旧 路径

a.vue 子页
//跳转前先把当前路径保存到全局vuex变量lastFullPath
this.$store.commit('setLastFullPath',route.fullPath)//保存路由用于返回本页
this.$router.replace('/ ');//清空路由,不重置会导致url 混乱。
this.$router.replace(`b/`+route.name+`/in?id=`+id);

以上所述就是小编给大家介绍的《记 vue 移动端开发 中的经验》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

3D打印

3D打印

[美]胡迪•利普森,梅尔芭•库曼 / 赛迪研究院专家组 / 中信出版社 / 2013-4 / 49.00元

《3D打印:从想象到现实》内容简介:你需要一把功能强大的锤子?你需要一双精致无比的鞋子?你需要给孩子准备奇异的玩具?你需要一顿精美的晚餐?只管打印出来就行了。《3D打印:从想象到现实》带你走进3D打印的世界,认识一下当下这个最酷的东西——它将从想象变成现实,并带来一场深刻的社会革命。 书中讲述了3D打印技术的突破性发展,以及3D打印技术将如何应用在学校、厨房、医院等场所的。《3D打印:从想象......一起来看看 《3D打印》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码