項(xiàng)目介紹
基于vue-cli@2.0的常用配置,代碼切換到vuecli@2.0分支查看荒辕;
后期基于vue-cli@3.0進(jìn)行配置優(yōu)化,具體查看基于vue-cli@3.0搭建管理系統(tǒng)項(xiàng)目并進(jìn)行配置優(yōu)化
基于vue2.0項(xiàng)目開發(fā)中的一些思路
主要包括:
使用腳手架初始化項(xiàng)目
將需要用到的工具函數(shù)新建一個(gè)utils文件夾統(tǒng)一管理
使用router的一些優(yōu)化
使用Vuex的一些優(yōu)化
封裝axios及統(tǒng)一管理api
# 在項(xiàng)目目錄和server目錄分別進(jìn)行安裝依賴
git clone git@github.com:crui14994/Vue_Init-Config.git
# 在項(xiàng)目目錄和server目錄分別進(jìn)行安裝依賴
cnpm install
# 運(yùn)行項(xiàng)目
npm run dev
使用腳手架初始化項(xiàng)目
# 安裝cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 用cnpm 命令安裝vue-cli了汗销,在命令行輸入下面的命令:
cnpm install vue-cli -g
# 用vue init命令來初始化項(xiàng)目
vue init webpack-simple Vue_Init-Config
# 在項(xiàng)目目錄和server目錄分別進(jìn)行安裝依賴
cnpm install
# 運(yùn)行項(xiàng)目
npm run dev
將需要用到的工具函數(shù)新建一個(gè)utils文件夾統(tǒng)一管理
在根目錄新建一個(gè)utils文件夾
-
在文件夾下新建index.js用于幾種管理工具函數(shù)
export default { storage: require('./storage.js').default, //本地存儲(chǔ)localStorage formatDate: require('./formatDate.js').default, //日期格式化 }
-
編寫工具函數(shù)導(dǎo)出右index.js導(dǎo)入
/** formatDate.js * 格式化日期 * @param {string} str 需要格式化的樣子 * @param {String|Date} day 日期對象或者日期字符串 * @return {String} * @template formatDate('YYYY年mm月dd日hh小時(shí)ff分鐘ss秒 星期w','2017/1/1 12:13:14') 返回:2017年01月01日12小時(shí)13分鐘14秒 星期日; */ function formatDate (str, day) { let d, arr let type = Object.prototype.toString.call(day) if (type === '[object Date]') { d = day } else if (type === '[object String' && (arr = day.match(/(\d{4})[-/](\d{1,2})[-/](\d{1,2})(?:\s+(\d{1,2}):(\d{1,2}):(\d{1,2}))?/))) { arr = arr.slice(0, arr[4] ? 7 : 4) arr[2] = arr[2] - 1 d = new (Function.prototype.bind.apply(Date, arr))() } else { return '' } const obj = { 'yyyy': d.getFullYear(), 'yy': ('' + d.getFullYear()).slice(-2), 'm': d.getMonth() + 1, 'mm': ('0' + (d.getMonth() + 1)).slice(-2), 'd': d.getDate(), 'dd': ('0' + d.getDate()).slice(-2), 'h': d.getHours(), 'hh': ('0' + d.getHours()).slice(-2), 'f': d.getMinutes(), 'ff': ('0' + d.getMinutes()).slice(-2), 's': d.getSeconds(), 'ss': ('0' + d.getSeconds()).slice(-2), 'w': ['日', '一', '二', '三', '四', '五', '六'][d.getDay()] } return ('' + str).replace(/([a-z]+)/ig, function (k) { return obj[k.toLowerCase()] || '' }) } export default formatDate
/*storage.js *本地存儲(chǔ)localStorage */ class Storage { constructor () { this.storage = window.localStorage this.prefix = 'mytest_' //給key家一個(gè)前綴 } set (key, value, fun) { if (typeof value !== 'string') { try { value = JSON.stringify(value) } catch (e) { } } this.storage.setItem(this.prefix + key, value) typeof fun === 'function' && fun() } get (key, fun) { let value = this.storage.getItem(this.prefix + key) try { value = JSON.parse(value) if (value === null) value = {} } catch (e) { value = {} } return typeof fun === 'function' ? fun.call(this, value) : value } remove (key) { this.storage.removeItem(this.prefix + key) } cle() { this.storage.clear(); } } export default new Storage() ```
-
在main.js中把通用方法掛載到Vue原型上在組件中只需使用this即可使用相關(guān)的函數(shù)
import utils from "./utils/index" //導(dǎo)入工具函數(shù) // 把通用方法掛載到Vue原型上 Vue.prototype.$formatDate = utils.formatDate Vue.prototype.$storage = utils.storage
-
在組件中使用
computed:{ dateNow(){ return this.$formatDate('YYYY年mm月dd日hh小時(shí)ff分鐘ss秒 星期w',new Date()) } }
使用vue-router的一些優(yōu)化(代碼中只提供思路;沒有具體實(shí)現(xiàn))
-
在根目錄新建一個(gè)router文件夾抵窒;安裝vue-router
cnpm install vue-router --save-dev
-
在文件夾下新建index.js和route.js兩個(gè)文件
在index.js中對路由進(jìn)行配置弛针;
在route.js中對各個(gè)路徑進(jìn)行配置(具體參考源碼)
import Vue from 'vue'; import VueRouter from 'vue-router'; import { routers } from './route'; // import { Loading } from 'element-ui'; // import { setTitle } from 'src/assets/js/util'; Vue.use(VueRouter); const routerConfig = { mode: 'history', linkActiveClass: 'active', routes: routers }; const router = new VueRouter(routerConfig); // let loading; // router.beforeEach((to, form, next) => { // loading = Loading.service({ // // fullscreen: true, // target: '.content-wrapper', // text: '跳轉(zhuǎn)中...' // }); // // 設(shè)置window.document.title 的名稱 // setTitle(to.meta.title); // if (!to.matched.length) { // next({ // path: '/error/404', // replace: true // }); // } else { // next(); // } // }); // router.afterEach((to, from) => { // // 解決某些情況下loading無法關(guān)閉的情況 // setTimeout(() => { // loading.close(); // }, 0) // }); export default router;
-
在main.js中引入router
import router from './router/index';
使用Vuex的一些優(yōu)化
-
在根目錄新建一個(gè)store文件夾;安裝vue-router
cnpm install vuex --save
-
在文件夾下新建index.js和user.js兩個(gè)文件
在index.js引入我們的vue和vuex
在user.js中定義user需要使用到的狀態(tài)
//index.js import Vue from 'vue'; import Vuex from 'vuex'; import user from './user'; Vue.use(Vuex); export default new Vuex.Store({ modules: { user } });
//user.js import utils from "./../utils/index"; const state = { //token token: utils.storage.get("token") }; const mutations = { setToken(state, data) { state.token = data; } }; export default { state, mutations };
-
在main.js中引入router
//sotre import store from "./store/index";
封裝axios李皇;統(tǒng)一管理api
-
在utils下新建axios.js文件
import axios from 'axios' // import { Message } from 'element-ui' //sotre import store from "./../store/index"; import qs from 'qs' // 序列化請求數(shù)據(jù)削茁,視服務(wù)端的要求 // 創(chuàng)建axios實(shí)例 const service = axios.create({ //這里baseurl就是剛開始配置的開發(fā)環(huán)境和線上環(huán)境地址,webpack會(huì)自動(dòng)讀取無需手動(dòng)再改 baseURL: process.env.BASE_URL, //baseurl timeout: 5000 // 請求超時(shí)時(shí)間 }) // request攔截器 service.interceptors.request.use(config => { // Tip: 1 // 請求開始的時(shí)候可以結(jié)合 vuex 開啟全屏的 loading 動(dòng)畫 // Tip: 2 // 帶上 token , 可以結(jié)合 vuex 或者重 localStorage // if (store.getters.token) { // config.headers['X-Token'] = getToken() // 讓每個(gè)請求攜帶token--['X-Token']為自定義key 請根據(jù)實(shí)際情況自行修改 // } else { // // 重定向到登錄頁面 // } // Tip: 3 // 根據(jù)請求方法掉房,序列化傳來的參數(shù)茧跋,根據(jù)后端需求是否序列化 if (config.method.toLocaleLowerCase() === 'post' || config.method.toLocaleLowerCase() === 'put' || config.method.toLocaleLowerCase() === 'delete') { config.data = qs.stringify(config.data) } return config }, error => { // 請求錯(cuò)誤時(shí)做些事(接口錯(cuò)誤、超時(shí)等) // Tip: 4 // 關(guān)閉loadding console.log('request:', error); return Promise.reject(error) // 在調(diào)用的那邊可以拿到(catch)你想返回的錯(cuò)誤信息 }) // respone攔截器 service.interceptors.response.use( response => response, /** * 下面的注釋為通過response自定義code來標(biāo)示請求狀態(tài)卓囚,當(dāng)code返回如下情況為權(quán)限有問題瘾杭,登出并返回到登錄頁 * 如通過xmlhttprequest 狀態(tài)碼標(biāo)識(shí) 邏輯可寫在下面error中 */ // const res = response.data; // if (res.code !== 20000) { // Message({ // message: res.message, // type: 'error', // duration: 5 * 1000 // }); // // 50008:非法的token; 50012:其他客戶端登錄了; 50014:Token 過期了; // if (res.code === 50008 || res.code === 50012 || res.code === 50014) { // MessageBox.confirm('你已被登出,可以取消繼續(xù)留在該頁面哪亿,或者重新登錄', '確定登出', { // confirmButtonText: '重新登錄', // cancelButtonText: '取消', // type: 'warning' // }).then(() => { // store.dispatch('FedLogOut').then(() => { // location.reload();// 為了重新實(shí)例化vue-router對象 避免bug // }); // }) // } // return Promise.reject('error'); // } else { // return response.data; // } error => { console.log('err' + error)// for debug // Message({ // message: error.message, // type: 'error', // duration: 5 * 1000 // }) return Promise.reject(error) }) export default service
-
在src下新建目錄api和user.js文件
import service from "./../utils/axios"; export function mock(apiRouter) { return service({ url: "https://easy-mock.com/mock/5c9c8e9ba0feb92705bf12b7/example/"+apiRouter, method: "get", }); }
-
在組件中的使用
import { mock } from "./api/user"; created() { mock("mock").then(response => { this.reponseData = response.data; }); }