基于Vue-Cli3的Vue移动端企业级工程架构
本项目是基于Vue-Cli3脚手架,应用VW的自适应解决方案构建的移动端企业级工程项目,下面会一步步构建起项目结构。大家也可以先下载源代码下来看下,再跟着操作。
Author: Gavin
项目地址:https://github.com/PowerDos/vue-cli-3-mobile-vm-demo
演示
下面是一张自适应效果git图,比较大,需要耐心等待才能看到,或者直接下载图片查看效果[https://i.loli.net/2019/12/03/oONsfGkgit7H3Cw.gif]
工程目录
这里展示的是最终的目录结构,方便查看,后面会一步步说明并搭建此目录
.
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── public
│ └── index.html
├── src
│ ├── App.vue
│ ├── api
│ │ └── homeApi.js
│ ├── assets
│ │ ├── img
│ │ │ └── head.png
│ │ └── scss
│ │ └── global.scss
│ ├── components
│ │ └── Footer.vue
│ ├── main.js
│ ├── page
│ │ └── Home.vue
│ ├── router
│ │ └── index.js
│ ├── store
│ │ ├── actions.js
│ │ ├── getters.js
│ │ ├── index.js
│ │ ├── modules
│ │ │ └── home.js
│ │ └── mutations.js
│ └── utils
│ ├── http.js
│ └── tool.js
└── vue.config.js
基础项目创建
创建项目
$: vue create vue_cli_3_mobile_vm_demo
选择默认模式
$: Please pick a preset: **default (babel, eslint)
补全 Eslint 依赖
$: npm install eslint-config-standard eslint-friendly-formatter eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-standard --save-dev
配置Eslint规则
配置统一规则,团队开发统一规范,在根目录创建文件.eslintrc.js。(PS:配置完规则后,需要根据自身开发工具安装Eslint插件,如VSCode,安装ESLint插件)
可以根据自身团队的习惯,指定规则,下面只是一种参考
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint'
},
env: {
browser: true,
},
extends: [
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
'plugin:vue/essential',
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
'standard'
],
// required to lint *.vue files
plugins: [
'vue'
],
// add your custom rules here
rules: {
"semi": [2, "always"],
// allow async-await
'generator-star-spacing': 'off',
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
}
}
支持SASS/SCSS
$: npm install sass-loader node-sass --save-dev
创建全局SCSS
创建全局scss文件./src/scss/global.scss
// 文件中可以写全局的变量,包括字体大小,主题色,边距大小等,这样可以方便后面整个项目风格修改
// 主题 - 蓝
$primary-color: #03A9F4;
$primary-color-dark: #409EFF;
$primary-color-light:#B3E5FC;
$primary-color-rgba-1: rgba(3,169,244,.1);
$primary-color-rgba-2: rgba(3,169,244,.2);
$background-color: #F0F2F5;
// 文字样式
$title-text-color: #303133;
$normal-text-color: #606266;
$sub-text-color: #909399;
$temp-text-color: #C0C4CC;
根目录创建vue.config.js,引入全局文件
module.exports = {
...
css: {
loaderOptions: {
sass: {
// 根据自己样式文件的位置调整
prependData: '@import "@/assets/scss/global.scss";'
}
}
}
...
};
移动端自适应
具体可以了解下https://www.w3cplus.com/css/vw-for-layout.html,这里有讲到一些原理,这里不做展开
安装依赖
$: npm i postcss-aspect-ratio-mini postcss-px-to-viewport postcss-write-svg postcss-cssnext postcss-viewport-units postcss-import postcss-cssnext cssnano cssnano-preset-advanced postcss-import postcss-url --save-dev
配置规则,修改vue.config.js
module.exports = {
...
css: {
loaderOptions: {
sass: {
// 根据自己样式文件的位置调整
prependData: '@import "@/assets/scss/global.scss";'
},
postcss: {
plugins: [
require('postcss-px-to-viewport')({
viewportWidth: 750,
viewportHeight: 1334,
unitPrecision: 3,
viewportUnit: 'vw',
"selectorBlackList": [".ignore", ".hairlines"], // 这里是过滤不转换的css,支持正则,如果框架本身把单位写死支持移动端,可以通过这个过滤掉,比如vux UI框架需要过滤掉['.ignore', '.hairlines', /^\.weui/, /^\.dp/, /^\.scroller/, /^\.ignore/],
minPixelValue: 1,
mediaQuery: false
})
]
}
}
}
...
};
工程目录搭建
加入路由Vue-Router, 状态存储Vuex, HTTP请求axios
$: npm install vue-router veux axios --save
在src文件夹创建工程目录
.
├── App.vue // VUE总入口
├── api // API请求文件夹
│ └── homeApi.js // 分模块写请求文件
├── assets // 静态文件
│ ├── img // 图片资源
│ │ └── head.png
│ └── scss // scss样式资源
│ └── global.scss
├── components // 抽象出来的组建
│ └── SubTitle.vue
├── main.js // Vue主文件
├── page // 应用页面
│ └── Home.vue
├── router // 路由
│ └── index.js
├── store // 状态存储
│ ├── actions.js
│ ├── getters.js
│ ├── index.js
│ ├── modules
│ │ └── home.js
│ └── mutations.js
└── utils // 工具
├── http.js
└── tool.js
mian 文件引入vue-router和vuex
import Vue from 'vue';
import App from './App.vue';
import router from './router/index';
import store from './store/index';
Vue.config.productionTip = false;
new Vue({
store,
router,
render: h => h(App)
}).$mount('#app');
App.vue引入路由
路由创建创立
创建./src/router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import Home from '@/page/Home';
Vue.use(Router);
export default new Router({
routes: [
// 登陆
{
path: '/',
name: 'Home',
component: Home
}
]
});
创建状态存储
最外层的为全局状态管理(action.js/getters.js/index.js/mutations.js),modules下放的为每个模块单独的状态存储具体可以下载项目看具体代码内容
.
├── actions.js
├── getters.js
├── index.js
├── modules
│ └── home.js
└── mutations.js
这里展示index.js
import Vue from 'vue';
import Vuex from 'vuex';
// 引入全局存储
import * as actions from './actions';
import * as mutations from './mutations';
import * as getters from './getters';
// 引入模块存储
import home from './modules/home';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
globalFlag: 0
},
actions,
mutations,
getters,
modules: {
home
}
});
引入UI框架
这里以引入Vant UI为例
安装vant
$: npm install vant --save
按需引入
安装按需加载依赖,babel-plugin-import 是一款 babel 插件,它会在编译过程中将 import 的写法自动转换为按需引入的方式
$: npm install babel-plugin-import --save-dev
配置babel,修改根目录下的babel.config.js
module.exports = {
presets: [
'@vue/app'
],
plugins: [
[
'import',
{
libraryName: 'vant',
libraryDirectory: 'es',
style: true
},
'vant'
]
]
};
过滤px单位转换成VM
由于Vant UI本身就自带了自适应,所以无需转换为vw单位,我们可以再postcss上过滤掉,修改根目录的vue.config.js文件
module.exports = {
css: {
loaderOptions: {
sass: {
// 根据自己样式文件的位置调整
prependData: '@import "@/assets/scss/global.scss";'
},
postcss: {
plugins: [
require('postcss-px-to-viewport')({
viewportWidth: 750,
viewportHeight: 1334,
unitPrecision: 3,
viewportUnit: 'vw',
selectorBlackList: ['.ignore', '.hairlines', /^\.dp/, /^\.scroller/, /^\.van/], // 这里是过滤不转换的css,支持正则,如果框架本身把单位写死支持移动端,可以通过这个过滤掉
minPixelValue: 1,
mediaQuery: false
})
]
}
}
}
};
demo
1
2
3
4
效果
开发配置
由于大部分情况下,我们都是在本地开发,请求后端服务,所以我们这里可以直接在vue.config.js中配置测试服器地址或本地服务地址,这样我们就可以直接在本地测试服务端的功能,并且解决跨域问题
配置根目录下的vue.config.js
module.exports = {
...
devServer: {
proxy: {
'/api': { // 需要转发的接口,如果全转发就设置根就行/
target: 'http://xxxx:8080/', // 对应自己的接口
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': ''
}
}
}
},
...
};