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

初衷

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

UI组件选型

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

mint-ui使用过程

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

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

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

记录开发过程当中几个坑

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

这是在搭建框架的时候遇到的第一个问题,按照原先的经验,我先尝试使用了px2rem-loader来统一将px转换为rem,可是问题是,使用px2rem会将项目内全部css文件的px都转为rem,而mint-ui内的css是不能被转换的,由于其自己已经作了一些适配,可是并不基于rem的方式,因此若是强制将其内部的css文件作了转换,通常会致使全部其内部元素的尺寸变小。github

因此目的应该是将本身写的样式内容作rem转换,因此使用了postcss,缘由是postcss带有px2rem的插件。web

贴下vue-loader.conf.js:vue-router

'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()
复制代码

图片列表的横向滚动需求

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

这个需求的实现过程不过重要,须要的是要理解在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很好用,真的强烈推荐。睡觉,哔哔哔。

相关文章
相关标签/搜索