欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-13 20:50:17
...

今天正好有机会, 整理一下如何新建一个 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宽的
所以你要调整一下。

这里调整方式我给我两种方案
第一种 修改设计稿宽度 我这里使用的蓝湖
整理一下vue 移动端模板框架搭建
第二种 就是修改 postcss-pxtorem 转换规则 还是按750px 做

vue.config.js 需要改一下 不转换 vant 组件

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

最终效果
整理一下vue 移动端模板框架搭建

重要组件修改

  • 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