今天正好有机会, 整理一下如何新建一个 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框架
cnpm install vant -S 引入 babel-plugin-import
配置按需加载 需要修改 babel.config.js main.js 这两个文件
-- babel.config.js module.exports = {presets: ['@vue/app'],plugins: [['import', {libraryName: 'vant',libraryDirectory: 'es',style: true}, 'vant']]}-- main.jsimport {Button, NavBar, Cell } from 'vant'import 'vant/lib/button/style'Vue.use(Button).use(Cell).use(NavBar)
统一单位 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 (默认项目是没有的,自己新建在根目录 )
/*** 配置参考: /zh/config/*/module.exports = {publicPath: process.env.NODE_ENV === 'production' ? './' : '/',productionSourceMap: false,devServer: {open: true,port: 8017,proxy: {'/api': {target: '',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.pushRouter.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 = '请求的数据具有新的位置且更改是永久的'; breakcase 302: err.message = '请求的数据临时具有不同 URI'; breakcase 304: err.message = '未按预期修改文档'; breakcase 305: err.message = '必须通过代理来访问请求的资源'; breakcase 400: err.message = '请求中有语法问题,或不能满足请求'; breakcase 402: err.message = '所使用的模块需要付费使用'; breakcase 403: err.message = '当前操作没有权限'; breakcase 404: err.message = '服务器找不到给定的资源'; breakcase 407: err.message = '客户机首先必须使用代理认证自身'; breakcase 415: err.message = '请求类型不支持,服务器拒绝服务'; breakcase 417: err.message = '未绑定登录账号,请使用密码登录后绑定'; breakcase 426: err.message = '用户名不存在或密码错误'; breakcase 429: err.message = '请求过于频繁'; breakcase 500: err.message = '服务器内部错误,无法完成请求'; breakcase 501: err.message = '服务不支持请求'; breakcase 502: err.message = '网络错误,服务器接收到上上游服务器无效响应'; breakcase 503: err.message = '服务器无法处理请求'; breakcase 504: err.message = '网络请求超时'; breakcase 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 = falseVue.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