appvue.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: {}}上面一段配置只适用于自己。
src下设置一个common目录,然后把所有的css样式都放到里面。重置文件一般为reset.less,全局样式文件一般为base.less,字体及颜色目录文件一般为variable.less,在项目中要使用到的一些特殊样式为mixin.styl,字体图表样式为icon.less,出口问文件为index.styl。具体参考内容如下:index.styl文件:
@import "./base"@import "./reset"@import "./icon"@import "variable"reset.styl:
/*移动端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文件:
// 整体样式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文件:
// 颜色定义规范$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.867vwmixin.styl文件:
// 上边框1pxborder-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字体图标
目录结构
由于很少使用到vuex模块,为了更加的熟悉vuex模块,在此记录:
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
const state = { name:‘‘}export default states3.mutation-types.js
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 mutations5.getters.js
export const name = state => state.name6.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 文件里面可以直接调用方法从而异步获取数据的
原文:https://www.cnblogs.com/ginkgo-leaves/p/10751910.html