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很好用,真的強烈推薦。睡覺,嗶嗶嗶。

相關文章
相關標籤/搜索