整理一下vue 移動端模板框架搭建

今天正好有機會, 整理一下如何新建一個 vue 移動端模板框架

vue create vue_h5
回車

Vue CLI v4.1.1
? Please pick a preset:
  ee (router, vuex, babel)
  單元測試 (node-sass, babel, router, vuex, eslint, unit-jest)
  標準項目 (node-sass, babel, router, vuex, eslint)
  default (babel, eslint)
> Manually select features
回車

? Please pick a preset: Manually select features
? Check the features needed for your project:
 (*) Babel
 ( ) TypeScript
 (*) Progressive Web App (PWA) Support
 (*) Router
 (*) Vuex
>(*) CSS Pre-processors
 (*) Linter / Formatter
 ( ) Unit Testing
 ( ) E2E Testing

以上是我新建選擇的組件

移動端項目 最爲關鍵的就是 px => rem 單位轉換問題

引入Vant UI框架

  1. cnpm install vant -S 引入 babel-plugin-import

  2. 配置按需加載 需要修改 babel.config.js main.js 這兩個文件

    -- babel.config.js 
    module.exports = {
      presets: [
        '@vue/app'
      ],
      plugins: [
        ['import', {
          libraryName: 'vant',
          libraryDirectory: 'es',
          style: true
        }, 'vant']
      ]
    }
    -- main.js
    import { Button, NavBar, Cell } from 'vant'
    import 'vant/lib/button/style'
    
    Vue.use(Button).use(Cell).use(NavBar)
    
  3. 統一單位 px -> rem 需要用到 postcss-pxtorem lib-flexible (這裏方案很多,就不多說了)
    cnpm isntall lib-flexible -S
    cnpm install postcss-pxtorem -D
    main.js引入 import ‘lib-flexible/flexible’
    之後配置一下 vue.config.js (默認項目是沒有的,自己新建在根目錄 )

    /**
     * 配置參考: https://cli.vuejs.org/zh/config/
     */
    module.exports = {
      publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
      productionSourceMap: false,
      devServer: {
        open: true,
        port: 8017,
        proxy: {
          '/api': {
            target: 'http://apitest.oucnet.com',
            secure: false,
            ws: true,
            changeOrigin: true,
            pathRewrite: { '^/api': '' }
          }
        },
        overlay: {
          errors: true,
          warnings: true
        }
      },
      css: {
        loaderOptions: {
          postcss: {
            plugins: [
              require('postcss-pxtorem')({
                rootValue: 37.5, // 換算的基數
                propList: ['*']
              })
            ]
          }
        }
      }
    }
    

注: 這裏 publicPath 可能你用的是 vue-cli3 這個參數名稱應該是 baseUrl 我這裏是
vue-cli4.1.1, 我這裏的換算值是 37.5 對應的設計稿是 375 寬的 但是我們一般拿到的設計稿是 750寬的
所以你要調整一下。

這裏調整方式我給我兩種方案
第一種 修改設計稿寬度 我這裏使用的藍湖
在這裏插入圖片描述
第二種 就是修改 postcss-pxtorem 轉換規則 還是按750px 做

vue.config.js 需要改一下 不轉換 vant 組件

css: {
    loaderOptions: {
      postcss: {
        plugins: [
          require('postcss-pxtorem')({
            rootValue: 75, // 換算的基數
            propList: ['*'],
            selectorBlackList: ['.van-']
          })
        ]
      }
    }
  }

最終效果
在這裏插入圖片描述

重要組件修改

  • router/index.js 修改
import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

const routes = [
  {
    path: '*',
    component: () => import('@/views/pages/404'),
    name: '404',
    meta: { title: '404未找到' }
  },
  { path: '/', name: 'index', component: () => import('@/views/index'), meta: { title: '加載中···' } }
]

const router = new Router({
  mode: 'history',
  scrollBehavior: () => ({ y: 0 }),
  base: process.env.BASE_URL,
  routes
})

// 攔截器
router.beforeEach((to, from, next) => {
  // 動態標題
  window.document.title = to.meta.title
  // 處理業務問題...
  next()
})

// 處理Router的BUG 當前顯示的路由再次點擊會打印錯誤
const originalPush = Router.prototype.push
Router.prototype.push = function push (location) {
  return originalPush.call(this, location).catch(err => err)
}

export default router
  • axios 以及vuex 的配置 引入兩個組件 cnpm install lodash axios -S
    store/index.js 修改
import Vue from 'vue'
import Vuex from 'vuex'
import cloneDeep from 'lodash/cloneDeep'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  mutations: {
    // 重置vuex本地儲存狀態
    resetStore (state) {
      Object.keys(state).forEach((key) => {
        state[key] = cloneDeep(window.SITE_CONFIG['storeState'][key])
      })
    }
  },
  actions: {
  },
  modules: {
  }
})

axios 配置 我這裏在新建了 src/utils/request.js

import axios from 'axios'
import router from '@/router'
import { clearLoginInfo } from '@/utils'
import { Toast } from 'vant'
const http = axios.create({
  baseURL: window.SITE_CONFIG['apiURL'],
  timeout: 1000 * 180,
  withCredentials: true
})

/**
 * 請求攔截
 */
http.interceptors.request.use(config => {
  return config
}, error => {
  return Promise.reject(error)
})

/**
 * 響應攔截
 */
http.interceptors.response.use(response => {
  if (response.data.code === 401) {
    clearLoginInfo()
    router.replace({ name: 'login' })
    return Promise.reject(response.data.msg)
  }
  return response
}, err => {
  if (err && err.response) {
    switch (err.response.status) {
      case 301: err.message = '請求的數據具有新的位置且更改是永久的'; break
      case 302: err.message = '請求的數據臨時具有不同 URI'; break
      case 304: err.message = '未按預期修改文檔'; break
      case 305: err.message = '必須通過代理來訪問請求的資源'; break
      case 400: err.message = '請求中有語法問題,或不能滿足請求'; break
      case 402: err.message = '所使用的模塊需要付費使用'; break
      case 403: err.message = '當前操作沒有權限'; break
      case 404: err.message = '服務器找不到給定的資源'; break
      case 407: err.message = '客戶機首先必須使用代理認證自身'; break
      case 415: err.message = '請求類型不支持,服務器拒絕服務'; break
      case 417: err.message = '未綁定登錄賬號,請使用密碼登錄後綁定'; break
      case 426: err.message = '用戶名不存在或密碼錯誤'; break
      case 429: err.message = '請求過於頻繁'; break
      case 500: err.message = '服務器內部錯誤,無法完成請求'; break
      case 501: err.message = '服務不支持請求'; break
      case 502: err.message = '網絡錯誤,服務器接收到上上游服務器無效響應'; break
      case 503: err.message = '服務器無法處理請求'; break
      case 504: err.message = '網絡請求超時'; break
      case 999: err.message = '系統未知錯誤,請反饋給管理員'; break
    }
  } else {
    err.message = '連接服務器失敗!'
  }
  Toast(err.message)
  return Promise.reject(err)
})

export default http

main.js 配置

import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import router from './router'
import store from './store'
import { Button, NavBar, Cell } from 'vant'
import 'vant/lib/button/style'
import 'lib-flexible/flexible'
import cloneDeep from 'lodash/cloneDeep'
import http from '@/utils/request'

Vue.config.productionTip = false

Vue.use(Button).use(Cell).use(NavBar)

// 掛載全局
Vue.prototype.$http = http

// 保存整站vuex本地儲存初始狀態
window.SITE_CONFIG['storeState'] = cloneDeep(store.state)

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

配置 本地開發域名 上線上線打包域名 需要修改 index.html 和 package.json

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title>H5項目模板</title>

    <!-- 站點配置 -->
    <script>
      window.SITE_CONFIG = {};
      window.SITE_CONFIG['nodeEnv'] = '<%= process.env.VUE_APP_NODE_ENV %>';
      window.SITE_CONFIG['apiURL'] = '';                      // api請求地址
      window.SITE_CONFIG['storeState'] = {};                  // vuex本地儲存初始化狀態(用於不刷新頁面的情況下,也能重置初始化項目中所有狀態)
    </script>

    <!-- 本地測試環境 -->
    <% if (process.env.VUE_APP_NODE_ENV === 'dev') { %>
    <script>window.SITE_CONFIG['apiURL'] = '/api';</script>
    <% } %>
    <!-- 集成上線環境 -->
    <% if (process.env.VUE_APP_NODE_ENV === 'prod:sit') { %>
    <script>window.SITE_CONFIG['apiURL'] = 'http://127.0.0.1:1000';</script>
    <% } %>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but 05_h5 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>
"scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build --mode development",
    "build:sit": "vue-cli-service build --mode production.sit",
    "lint": "vue-cli-service lint"
  },

最後打包本地測試頁面 cnpm run build
打包上線頁面 cnpm run build:sit

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章