基于Vue-Cli3的Vue移動(dòng)端企業(yè)級工程架構(gòu)
本項(xiàng)目是基于Vue-Cli3腳手架,應(yīng)用VW的自適應(yīng)解決方案構(gòu)建的移動(dòng)端企業(yè)級工程項(xiàng)目,下面會一步步構(gòu)建起項(xiàng)目結(jié)構(gòu)。大家也可以先下載源代碼下來看下,再跟著操作。
Author: Gavin
項(xiàng)目地址:https://github.com/PowerDos/vue-cli-3-mobile-vm-demo
演示
下面是一張自適應(yīng)效果git圖,比較大,需要耐心等待才能看到,或者直接下載圖片查看效果[https://i.loli.net/2019/12/03/oONsfGkgit7H3Cw.gif]

工程目錄
這里展示的是最終的目錄結(jié)構(gòu),方便查看,后面會一步步說明并搭建此目錄
.
├── 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
基礎(chǔ)項(xiàng)目創(chuàng)建
創(chuàng)建項(xiàng)目
$: vue create vue_cli_3_mobile_vm_demo
選擇默認(rèn)模式
$: Please pick a preset: **default (babel, eslint)
補(bǔ)全 Eslint 依賴
$: npm install eslint-config-standard eslint-friendly-formatter eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-standard --save-dev
配置Eslint規(guī)則
配置統(tǒng)一規(guī)則,團(tuán)隊(duì)開發(fā)統(tǒng)一規(guī)范,在根目錄創(chuàng)建文件.eslintrc.js。(PS:配置完規(guī)則后,需要根據(jù)自身開發(fā)工具安裝Eslint插件,如VSCode,安裝ESLint插件)
可以根據(jù)自身團(tuán)隊(duì)的習(xí)慣,指定規(guī)則,下面只是一種參考
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
創(chuàng)建全局SCSS
創(chuàng)建全局scss文件./src/scss/global.scss
// 文件中可以寫全局的變量,包括字體大小,主題色,邊距大小等,這樣可以方便后面整個(gè)項(xiàng)目風(fēng)格修改
// 主題 - 藍(lán)
$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;
根目錄創(chuàng)建vue.config.js,引入全局文件
module.exports = {
...
css: {
loaderOptions: {
sass: {
// 根據(jù)自己樣式文件的位置調(diào)整
prependData: '@import "@/assets/scss/global.scss";'
}
}
}
...
};
移動(dòng)端自適應(yīng)
具體可以了解下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
配置規(guī)則,修改vue.config.js
module.exports = {
...
css: {
loaderOptions: {
sass: {
// 根據(jù)自己樣式文件的位置調(diào)整
prependData: '@import "@/assets/scss/global.scss";'
},
postcss: {
plugins: [
require('postcss-px-to-viewport')({
viewportWidth: 750,
viewportHeight: 1334,
unitPrecision: 3,
viewportUnit: 'vw',
"selectorBlackList": [".ignore", ".hairlines"], // 這里是過濾不轉(zhuǎn)換的css,支持正則,如果框架本身把單位寫死支持移動(dòng)端,可以通過這個(gè)過濾掉,比如vux UI框架需要過濾掉['.ignore', '.hairlines', /^\.weui/, /^\.dp/, /^\.scroller/, /^\.ignore/],
minPixelValue: 1,
mediaQuery: false
})
]
}
}
}
...
};
工程目錄搭建
加入路由Vue-Router, 狀態(tài)存儲Vuex, HTTP請求axios
$: npm install vue-router veux axios --save
在src文件夾創(chuàng)建工程目錄
.
├── App.vue // VUE總?cè)肟?├── api // API請求文件夾
│ └── homeApi.js // 分模塊寫請求文件
├── assets // 靜態(tài)文件
│ ├── img // 圖片資源
│ │ └── head.png
│ └── scss // scss樣式資源
│ └── global.scss
├── components // 抽象出來的組建
│ └── SubTitle.vue
├── main.js // Vue主文件
├── page // 應(yīng)用頁面
│ └── Home.vue
├── router // 路由
│ └── index.js
├── store // 狀態(tài)存儲
│ ├── 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引入路由
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'app',
components: {}
};
</script>
<style>
/* 去除默認(rèn)自帶的所有邊距 */
html, body {
margin: 0px;
padding: 0px;
}
</style>
路由創(chuàng)建創(chuàng)立
創(chuàng)建./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
}
]
});
創(chuàng)建狀態(tài)存儲
最外層的為全局狀態(tài)管理(action.js/getters.js/index.js/mutations.js),modules下放的為每個(gè)模塊單獨(dú)的狀態(tài)存儲具體可以下載項(xiàng)目看具體代碼內(nèi)容
.
├── 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
}
});
引入U(xiǎn)I框架
這里以引入Vant UI為例
安裝vant
$: npm install vant --save
按需引入
安裝按需加載依賴,babel-plugin-import 是一款 babel 插件,它會在編譯過程中將 import 的寫法自動(dòng)轉(zhuǎn)換為按需引入的方式
$: 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單位轉(zhuǎn)換成VM
由于Vant UI本身就自帶了自適應(yīng),所以無需轉(zhuǎn)換為vw單位,我們可以再postcss上過濾掉,修改根目錄的vue.config.js文件
module.exports = {
css: {
loaderOptions: {
sass: {
// 根據(jù)自己樣式文件的位置調(diào)整
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/], // 這里是過濾不轉(zhuǎn)換的css,支持正則,如果框架本身把單位寫死支持移動(dòng)端,可以通過這個(gè)過濾掉
minPixelValue: 1,
mediaQuery: false
})
]
}
}
}
};
demo
<template>
<div class="home-container">
<!-- 導(dǎo)航 -->
<van-nav-bar :title="title" left-text="返回" left-arrow>
<van-icon name="shopping-cart-o" slot="right" info="9" size="20px"/>
</van-nav-bar>
<!-- 通知欄 -->
<van-notice-bar :text="notify" left-icon="volume-o" />
<!-- 輪播圖 -->
<van-swipe :autoplay="3000" indicator-color="white" class="swipe-container">
<van-swipe-item class="swipe-box swipe-color-1">1</van-swipe-item>
<van-swipe-item class="swipe-box swipe-color-2">2</van-swipe-item>
<van-swipe-item class="swipe-box swipe-color-3">3</van-swipe-item>
<van-swipe-item class="swipe-box swipe-color-4">4</van-swipe-item>
</van-swipe>
<!-- 菜單 -->
<van-grid :column-num="3">
<van-grid-item icon="like-o" text="收藏" />
<van-grid-item icon="clock-o" text="歷史訂單" />
<van-grid-item icon="balance-o" text="資金管理" />
<van-grid-item icon="setting-o" text="設(shè)置" />
<van-grid-item icon="location-o" text="收貨地址" />
<van-grid-item icon="service-o" text="服務(wù)中心" />
</van-grid>
<!-- 懶加載 -->
<van-skeleton title avatar :row="3" class="skeleton-box"/>
<van-skeleton title avatar :row="3" class="skeleton-box"/>
<van-skeleton title avatar :row="3" class="skeleton-box"/>
<!-- 底部 -->
<Footer :msg="copyright"></Footer>
</div>
</template>
<script>
import { Icon, NavBar, NoticeBar, Grid, GridItem, Swipe, SwipeItem, Skeleton } from 'vant';
import Footer from '@/components/Footer';
import { mapState } from 'vuex';
export default {
name: 'Home',
components: {
Footer,
[Icon.name]: Icon,
[NavBar.name]: NavBar,
[NoticeBar.name]: NoticeBar,
[Grid.name]: Grid,
[GridItem.name]: GridItem,
[Swipe.name]: Swipe,
[SwipeItem.name]: SwipeItem,
[Skeleton.name]: Skeleton
},
data () {
return {
title: 'Vue 企業(yè)級工程架構(gòu)',
notify: '本項(xiàng)目是基于Vue-Cli3腳手架,應(yīng)用VW的自適應(yīng)解決方案構(gòu)建的移動(dòng)端企業(yè)級工程項(xiàng)目,下面會一步步構(gòu)建起項(xiàng)目結(jié)構(gòu),方便大家了解整個(gè)過程。'
};
},
computed: {
...mapState(['copyright'])
}
};
</script>
<style lang="scss" scoped>
.home-container {
width: 100vw;
min-height: 100vh;
background-color: #fff;
.swipe-container {
height: 380px;
.swipe-box {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
font-size: 58px;
color: #fff;
}
.swipe-color-1 {
background-color: #845EC2;
}
.swipe-color-2 {
background-color: #FFC75F;
}
.swipe-color-3 {
background-color: #008E9B;
}
.swipe-color-4 {
background-color: #4D8076;
}
}
.skeleton-box {
margin-top: 15px;
}
}
</style>
效果
開發(fā)配置
由于大部分情況下,我們都是在本地開發(fā),請求后端服務(wù),所以我們這里可以直接在vue.config.js中配置測試服器地址或本地服務(wù)地址,這樣我們就可以直接在本地測試服務(wù)端的功能,并且解決跨域問題
配置根目錄下的vue.config.js
module.exports = {
...
devServer: {
proxy: {
'/api': { // 需要轉(zhuǎn)發(fā)的接口,如果全轉(zhuǎn)發(fā)就設(shè)置根就行/
target: 'http://xxxx:8080/', // 對應(yīng)自己的接口
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': ''
}
}
}
},
...
};