整理一下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框架
-
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.js import { 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 (默认项目是没有的,自己新建在根目录 )/** * 配置参考: 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