Vuejs 配合 mint-ui 开发移动端web

初衷

这是一个比较着急的事情(两天时间,写一个带视频播放、图片浏览、图文混排列表、上拉刷新、滚动刷新等等的单页),一开始同事使用传统H5+JS+CSS的方式,我担心进度,就硬着头皮上vuejs,为什么说硬着头皮上,原因是这是第二次在项目中使用vuejs,第一次使用的经历并不太好,主要是vuejs在低版本android端的适配确实让人头疼。

UI组件选型

还是说回到第一次使用vuejs的事情,当时选择了元素较为丰富的element-ui,因为确实元素上和产品设计上比较吻合,就没去寻找其他组件,无奈最后因为element-ui主打pcweb,导致移动端上UI适配问题突出,趟了很多坑。这次更加理智些,选择了饿了么团队的主打移动端的mint-ui,目前来说体验很好。

mint-ui使用过程

Mint-ui维护的很不错,使用起来也足够方便,我的基本的使用流程是这样的:

  • 首先在手机上体验其demo,扫描链接:


    image.png

Mint UI
挨个体验其中的提供的组件demo,评估是否满足自己需求,也对其支持的内容心里有个数。

image.png

记录开发过程中几个坑

移动端rem适配(含mint-ui的情况下)

这是在搭建框架的时候遇到的第一个问题,按照原先的经验,我先尝试使用了px2rem-loader来统一将px转换为rem,但是问题是,使用px2rem会将项目内所有css文件的px都转为rem,而mint-ui内的css是不能被转换的,因为其本身已经做了一些适配,但是并不基于rem的方式,所以如果强制将其内部的css文件做了转换,一般会导致所有其内部元素的尺寸变小。

所以目的应该是将自己写的样式内容做rem转换,所以使用了postcss,原因是postcss带有px2rem的插件。

贴下vue-loader.conf.js:

'use strict'
const utils = require('./utils')
const config = require('../config')
const precss = require('precss')
const pxtorem = require('postcss-px2rem')
const autoprefixer = require('autoprefixer')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
  ? config.build.productionSourceMap
  : config.dev.cssSourceMap

module.exports = {
  loaders: utils.cssLoaders({
    sourceMap: sourceMapEnabled,
    extract: isProduction
  }),
  postcss:[
      precss(),
      autoprefixer({
          browsers: [
              'last 10 Chrome versions',
              'last 5 Firefox versions',
              'Safari >= 6',
              'ie > 8'
          ]
      }),
      pxtorem({
          remUnit: 75 //设计尺寸的1/10
      })
  ],
  cssSourceMap: sourceMapEnabled,
  cacheBusting: config.dev.cacheBusting,
  transformToRequire: {
    video: ['src', 'poster'],
    source: 'src',
    img: 'src',
    image: 'xlink:href'
  }
}

Main.js中动态设置root节点的fontsize,配合rem适配响应式:

// px2rem
window.onresize = setHtmlFontSize
function setHtmlFontSize () {
  const htmlWidth = document.documentElement.clientWidth || document.body.clientWidth
  const htmlDom = document.getElementsByTagName('html')[0]
  htmlDom.style.fontSize = htmlWidth / 10 + 'px'
}
setHtmlFontSize()

图片列表的横向滚动需求

需求中需要的横向滚动就是类似:

image.png

这个需求的实现过程不太重要,需要的是要理解在WEB滚动的原理:
* 纵向可滚动的原理是,当浏览器(webview)的可视高度小于承载的内容高度时,即可滚动,也即会出现滚动条,比如平时的无限纵向列表。
* 横向可滚动的原理类似,当某个容器的横向可视宽度小于承载内容的宽度时,即可横向滚动。

这里的实现方式是使用了一个较好的vue滚动组件,better-scroll。

模板的层级有要求: itemContainer -> imageWrapper -> imageItem,其中itemContainer需要固定宽度和隐藏滚动条。

<div class="itemImage" ref="itemContainer">
      <!--需要支持横向滚动-->
      <ul ref="imageWrapper">
        <li class="image_item" :key="image.id" v-for="(image, index) in item.images" ref="imageItem">
          <img class="image" :src="image.big"/>
        </li>
      </ul>
    </div>
.itemImage {
  overflow: hidden;
  width: 750px;
}

方法中使用到了vue的nextTick,nextTick可以指定下一次DOM更新之后再执行的方法。

mounted () {
      this.$nextTick(() => {
        this.initImageScroll()
      })
  },
methods: {
   initImageScroll: function () {
      let width = 0
      for (let i = 0; i < this.item.images.length; i++) {
        width += this.$refs.imageItem[0].getBoundingClientRect().width
      }
      this.$refs.imageWrapper.style.width = width + 'px'
      this.$nextTick(() => {
        if (!this.scroll) {
          this.scroll = new BScroll(this.$refs.itemContainer, {
            startX: 0,
            click: true,
            scrollX: true,
            scrollY: false,
            eventPassthrough: 'vertical'
          })
        } else {
          this.scroll.refresh()
        }
      })
    },
}

路由跳转返回后的自动滚动复位问题

这个问题在vue-router的官方问题中有说明:滚动行为 | Vue Router 这里只贴下在vue-router实例化时加入实现的样子:

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Main',
      component: Main,
      meta: {
        keepAlive: true
      }
    },
    {
      path: '/ImagePlayer',
      name: 'ImagePlayer',
      component: ImagePlayer,
      meta: {
      }
    }
  ],
  scrollBehavior (to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition
    } else {
      if (from.meta.keepAlive) {
        from.meta.savedPosition = document.body.scrollTop
      }
      return { x: 0, y: to.meta.savedPosition || 0 }
    }
  }
})

子元素浮层滚动时阻止父元素随动问题

这个需求其实很常见,出现浮层后,在浮层上展示内容,当在浮层上有滚动操作是,需要防止底部元素同时滚动。我这里的解决方法是用position=fixed的方式来固定。
* 当浮层出现时,动态将底部元素的根元素设置为fixed,并记录当前的scrollY值
* 当浮层消失后,动态将底部元素的根元素设置回原始值,并滚回到scrollY位置(由于重新设置position后会位置复位)

实现方法如下:

   /**
     * 防止浮层唤起时底部滑动跟随问题
     * @param isFixed
     */
    stopBodyScroll: function (isFixed) {
      let bodyEl = document.getElementById('main')
      if (isFixed) {
        this.saveMainTop = window.scrollY
        bodyEl.style.position = 'fixed'
        bodyEl.style.top = -this.saveMainTop + 'px'
      } else {
        bodyEl.style.position = ''
        bodyEl.style.top = ''
        window.scrollTo(0, this.saveMainTop)
      }
    }

使用mt-loadmore时loading不消失问题

这个问题是文档没看清楚导致的,没有在正确的时机调用其内部子组件的onTopLoaded
方法导致,这里记录下mt-loadmore做下拉刷新的的方式:代码只保留了片段,在loadtop方法里有两个loadmore的ref原因是,在我的应用里分两个tab,同时都有下拉刷新功能,这里扔出来的原因是,大家需要注意,在同一个组件内,如果使用了多个mt-loadmore组件,那需要标识不同的ref值,比如我这里的loadmore1和loadmore2,要不然当调用onTopLoaded方法是会有各种异常出现,包括不能停止当前loading

 <!--下拉刷新列表-->
<template>
<div>
 <mt-loadmore 
        :top-method="loadTop" 
        :top-loading-text="null" 
        :top-drop-text="null"
        :top-pull-text="null"
     ref="loadmore1" 
        @top-status-change="handleTopChange">
</div>
</template>
<script>
export default {
   methods: {
    /**
     *  下拉刷新
     */
    loadTop: function () {
      if (this.selected === '1') {
        this.getYourData01(() => {
          this.$refs.loadmore1.onTopLoaded()
        })
      } else {
        this.getYourData02(() => {
          this.$refs.loadmore2.onTopLoaded()
        })
      }
    },
  }
}
</script>

结尾

Mint-ui很好用,真的强烈推荐。睡觉,哔哔哔。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容