app
vue.config.js
文件。常見配置以下:const path = require('path')
module.exports = {
// 基本路徑
publicPath: process.env.NODE_ENV === 'production'
? '/production-sub-path/'
: '/',
// 輸出文件目錄
outputDir: process.env.NODE_ENV === 'production' ? 'dist' : 'devdist',
// eslint-loader 是否在保存的時候檢查
lintOnSave: true,
/**
1. webpack配置,see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
**/
chainWebpack: () => {
},
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
// 爲生產環境修改配置...
} else {
// 爲開發環境修改配置...
}
config.resolve = { // 配置解析別名
extensions: ['.js', '.vue'],
alias: {
'@': path.resolve(__dirname, './src'),
'public': path.resolve(__dirname, './public'),
'components': path.resolve(__dirname, './src/components'),
'common': path.resolve(__dirname, './src/common'),
'views': path.resolve(__dirname, './src/views'),
'store': path.resolve(__dirname, './src/store'),
'assets': path.resolve(__dirname, './src/assets'),
'api': path.resolve(__dirname, './src/api'),
'test': path.resolve(__dirname, './src/test')
}
}
},
// 生產環境是否生成 sourceMap 文件
productionSourceMap: false,
// css相關配置
css: {
// 是否使用css分離插件 ExtractTextPlugin
extract: true,
// 開啓 CSS source maps?
sourceMap: false,
// css預設器配置項
loaderOptions: {
stylus: {
// 全局導入stylus樣式
data: `@import "~@/common/stylus/index.styl";`
}
},
// 啓用 CSS modules for all css / pre-processor files.
modules: true
},
// use thread-loader for babel & TS in production build
// enabled by default if the machine has more than 1 cores
parallel: require('os').cpus().length > 1,
/**
2. PWA 插件相關配置,see https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa
*/
pwa: {},
// webpack-dev-server 相關配置
devServer: {
open: false, // 編譯完成是否打開網頁
host: '0.0.0.0', // 指定使用地址,默認localhost,0.0.0.0表明能夠被外界訪問
port: 8080, // 訪問端口
https: false, // 編譯失敗時刷新頁面
hot: true, // 開啓熱加載
hotOnly: false,
proxy: null, // 設置代理
overlay: { // 全屏模式下是否顯示腳本錯誤
warnings: true,
errors: true
},
before: app => {
}
},
/**
3. 第三方插件配置
*/
pluginOptions: {}
}
上面一段配置只適用於本身。css
src
下設置一個common
目錄,而後把全部的css樣式都放到裏面。重置文件通常爲reset.less
,全局樣式文件通常爲base.less
,字體及顏色目錄文件通常爲variable.less
,在項目中要使用到的一些特殊樣式爲mixin.styl
,字體圖表樣式爲icon.less
,出口問文件爲index.styl
。具體參考內容以下:index.styl文件
:html
@import "./base"
@import "./reset"
@import "./icon"
@import "variable"
reset.styl
:vue
/*移動端css樣式重置,若是要修改全局樣式請在base.styl文件裏面修改*/
html {
font-family: "Helvetica Neue", Helvetica, STHeiTi, sans-serif;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%
}
html, body {
-webkit-user-select: none;
user-select: none;
}
html, body, div, object, iframe, applet,
object, h1, h2, h3, h4, h5, h6, p, blockquote,
pre, address, dl, dt, dd, ol, ul, li, table,
caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, figure,
figcaption, footer, header, menu, nav, output, ruby,
section, summary, time, mark, audio, video, progress {
margin: 0;
padding: 0;
border: 0;
vertical-align: baseline
}
a {
text-decoration: none;
-webkit-touch-callout: none;
background-color: transparent
}
li {
list-style: none
}
article, aside, details, figcaption, figure,
footer, header, main, menu, nav,
section, summary {
display: block
}
audio, canvas, progress, video {
display: inline-block
}
audio:not([controls]) {
display: none;
height: 0
}
[hidden], template {
display: none
}
a:active, a:hover {
outline: 0
}
abbr[title] {
border-bottom: 1px dotted
}
b, strong {
font-weight: bold
}
dfn {
font-style: italic
}
h1 {
font-size: 8.533vw;
margin: 2.859vw 0
}
small {
font-size: 80%
}
sub, sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline
}
sup {
top: -2.13vw;
bottom: -2.13vw
}
sub {
}
img {
border: 0;
-webkit-touch-callout: none;
}
svg:not(:root) {
overflow: hidden
}
figure {
margin: 4.2667vw 10.667vw
}
hr {
-moz-box-sizing: content-box;
box-sizing: content-box;
height: 0
}
pre {
overflow: auto
}
code, kbd, pre, samp {
font-family: monospace, monospace;
font-size: 4.267vw
}
a, button, input, optgroup, select, textarea {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
button, input, optgroup, select, textarea {
color: inherit;
font: inherit;
margin: 0;
-webkit-appearance: none;
outline: none;
line-height: normal
}
button {
overflow: visible
}
button, select {
text-transform: none
}
button, html input[type="button"], input[type="reset"], input[type="submit"] {
-webkit-appearance: button;
cursor: pointer
}
button[disabled], html input[disabled] {
cursor: default
}
button::-moz-focus-inner, input::-moz-focus-inner {
border: 0;
padding: 0
}
input {
line-height: normal
}
input[type="checkbox"], input[type="radio"] {
box-sizing: border-box;
padding: 0
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
height: auto
}
input[type="search"] {
-webkit-appearance: textfield;
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box;
box-sizing: content-box
}
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none
}
fieldset {
border: 1px solid silver;
margin: 0 2px;
padding: 1.493vw 2.667vw 3.2vw
}
legend {
border: 0;
padding: 0
}
textarea {
overflow: auto
}
optgroup {
font-weight: bold
}
table {
border-collapse: collapse;
border-spacing: 0
}
td, th {
padding: 0
}
base.styl文件
:webpack
// 總體樣式
body, html
line-height: 1
font-weight: 200
font-family: 'PingFang SC', 'STHeitiSC-Light', 'Helvetica-Light', arial, sans-serif
// 清除浮動
.clearfix
display: inline-block
&:after
display: block
content: "."
height: 0
line-height: 0
clear: both
visibility: hidden
// 圖片處理1.5倍像素屏幕1px處理與2倍像素屏幕1px處理
@media (-webkit-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5)
.border-1px
&::after
-webkit-transform: scaleY(0.7)
transform: scaleY(0.7)
@media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2)
.border-1px
&::after
-webkit-transform: scaleY(0.5)
transform: scaleY(0.5)
variable.styl文件
:ios
// 顏色定義規範
$color-background = #222
$color-background-d = rgba(0, 0, 0, 0.3)
$color-highlight-background = #333
$color-dialog-background = #666
$color-theme = #ffcd32
$color-theme-d = rgba(255, 205, 49, 0.5)
$color-sub-theme = #d93f30
$color-text = #fff
$color-text-d = rgba(255, 255, 255, 0.3)
$color-text-l = rgba(255, 255, 255, 0.5)
$color-text-ll = rgba(255, 255, 255, 0.8)
//字體定義規範
$font-size-10 = 2.667vw
$font-size-12 = 3.2vw
$font-size-14 = 3.733vw
$font-size-16 = 4.267vw
$font-size-18 = 4.8vw
$font-size-20 = 5.33vw
$font-size-22 = 5.867vw
mixin.styl文件
:git
// 上邊框1px
border-1px($color)
position: relative
&:after
display: block
position: absolute
left: 0
bottom: 0
width: 100%
border-top: 1px solid $color
content: ' '
// 沒有邊框
border-none()
&:after
display: none
// 圖片,3倍和2倍
bg-image($url)
background-image: url($url + "@2x.png")
@media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3)
background-image: url($url + "@3x.png")
值得說明的是字體圖標,項目通常會使用iconfont字體圖標github
目錄結構
因爲不多使用到vuex
模塊,爲了更加的熟悉vuex
模塊,在此記錄:web
index.js
import Vue from 'vue'
import Vuex from 'vuex'
import * as actions from './actions'
import * as getters from './getters'
import mutations from './mutations'
import states from './states'
Vue.use(Vuex)
export default new Vue.Store({
actions,
getters,
state,
mutations
})
2.state.js
vuex
const state = {
name:''
}
export default states
3.mutation-types.js
vue-cli
export const SET_NAME = set_name // 修更名字信息(請加上註釋)
4.mutations.js
import * as type from './mutation-types'
const mutations = {
[type.SET_NAME](state,name){
state.name = name
}
}
export mutations
5.getters.js
export const name = state => state.name
6.actions.js
import * as type from './mutation-types'
export const changeName = ({commit},{newName}){
commit(types.SET_NAME, newName)
}
axiox
的封裝能夠分爲三步,我的喜歡在項目目錄文件夾下創建一個api
文件來專門存放關於api
接口的一些東西http.js
用來專門封裝 axios
的接口設置,通常會和vue-axios使用
http.js文件
import axios from 'axios'
import vueAxios from 'vue-axios'
import Vue from 'vue'
import QS from 'qs'
Vue.use(vueAxios,axios)
// axios 環境設置
if(process.env.NODE_ENV === 'production'){
axios.defaults.baseURL= 'http://prouction.com'
}else if(process.env.NODE_ENV === 'development'){
axios.defaults.baseURL = 'http://development.com'
}else if(process.env.NODE_ENV === 'debug'){
axios.defaults.baseURL = 'http://debug.com'
}
// axios請求超時
axios.defaults.timeout = 10000
// post請求頭
axios.defaults.headers = {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
// 請求攔截器
axios.interceptors.request.use(
config=>{
// 每次發送請求以前判斷是否存在token,若是存在,則統一在http請求的header都加上token,不用每次請求都手動添加了
// 即便本地存在token,也有可能token是過時的,因此在響應攔截器中要對返回狀態進行判斷
// const token = store.state.user.token
// token && (config.headers.Authorization = `Bearer ${token}`)
config.data = QS.stringify(config.data)
return config
},
error => {
return Promise.error(error)
})
// 相應攔截器
let errorHandle = (status, other) => {
if (status) {
switch (status) {
/**
* 401: 未登陸
* 未登陸則跳轉登陸頁面,並攜帶當前頁面的路徑
*在登陸成功後返回當前頁面,這一步須要在登陸頁操做。
*/
case 401:
// tip('未登陸,請先登陸')
break
/**
* 403 token過時,登陸過時對用戶進行提示,清除本地token和清空vuex中token對象,跳轉登陸頁面
*/
case 403:
// tip('登陸過時,請從新登陸')
// setTimeout(() => {
// logout()
// }, 1000)
break
// 404請求不存在
case 404:
// tip('請求的資源不存在')
break
// 其餘錯誤,直接拋出錯誤提示
default:
// tip({
// message: error.response.data.message,
// duration: 1500, // 持續時間
// forbidClick: true
// })
console.log(other)
break
}
}
}
axios.interceptors.response.use(
// 拿到數據200
res => res.status === 200 ? Promise.resolve(res) : Promise.reject(res),
// 未拿到,非200
error => {
if (error.response === undefined) {
console.log('response:' + error.message)
return Promise.reject(error)
// tip('後臺錯誤,請求undfined')
}
errorHandle(error.response.status, error.response.data.message)
return Promise.reject(error.response)
}
)
/**
* 封裝接口調用方法
* @param url:地址
* @param data:傳入參數
* @param type:類型(僅限於get/post)
* @returns {Promise<any>}
* @constructor
*/
export function Axios (url, data = {}, type = 'GET') {
return new Promise((resolve, reject) => {
// 執行異步請求
let promise
if (type === 'GET') {
// 準備url的query參數數據
let dataStr = '' // 數據拼接字符串
Object.keys(data).forEach(key => {
dataStr += key + '=' + data[key] + '&'
})
if (dataStr !== '') {
dataStr = dataStr.substring(0, dataStr.lastIndexOf('&'))
url = url + '?' + dataStr
}
// get請求
promise = axios.get(url)
} else {
// 發送post請求
promise = axios.post(url, data)
}
promise.then(response => {
// 成功拿到response的data
resolve(response.data)
}).catch(error => {
reject(console.log(error))
})
})
}
base.js
裏面存放的是api接口模塊,全部的接口都存放在裏面:base.js文件
let baseURL = '10.10.21.86'
export nameURL = baseURL + '/name'
export let loginURL = baseURL + '/account/login'
export let guestURL = baseURL + '/account/guest'
export let regURL = baseURL + '/account/reg'
export let accountURL = baseURL + '/home/account'
export let kefuURL = baseURL + '/home/getkefu'
api.js
文件是獲取數據的接口方法模塊:
api.js文件
import {Axios} from './http'
import * as url from './base'
esport const getName = ({data})=>Axios(url.nameURL,{data},'POST')
在 vuex
的 actions.js
文件裏面能夠直接調用方法從而異步獲取數據的