Vue CLI 是一個基於 Vue.js 進行項目快速開發的腳手架javascript
注:具體安裝步驟可參考Vue CLI,默認安裝的腳手架,是沒有service、util等工具類的,如下主要描述如何在腳手架的基礎上進行快速開發
GitHub示例地址 vue-ht-cli
一,vue.config.js配置文件css
默認Vue CLI安裝完成後,是沒有這個配置文件的,須要手動在項目根目錄建立,並修改使用:html
如下爲我簡單配置的文件,更多詳細配置,請參考 Vue CLI官網vue
vue.config.jsjava
module.exports = { publicPath: process.env.NODE_ENV === "production" ? "./" : "/", // outputDir: 在npm run build時 生成文件的目錄 type:string, default:"dist" outputDir: "dist", // assetsDir 靜態文件目錄(js, css, img, fonts) under // assetsDir: "static", // lintOnSave:{ type:Boolean default:true } 問你是否使用eslint lintOnSave: true, // productionSourceMap:{ type:Bollean,default:true } 生產源映射 // 若是您不須要生產時的源映射,那麼將此設置爲false能夠加速生產構建 productionSourceMap: false, // devServer:{type:Object} 3個屬性host,port,https // 它支持webPack-dev-server的全部選項 devServer: { port: 8085, // 端口號 host: "192.168.3.49", //host: "localhost", https: false, open: false, //配置自動啓動瀏覽器 proxy: null } };
設置代理模式android
devServer: { proxy: { '/api': { target: '<url>', ws: true, changeOrigin: true }, '/foo': { target: '<other_url>' } } }
二,使用postcss-pxtorem自動px轉換爲remios
注:根據UI設計稿的比例(750、375等),設置rootValue的值git
開發時直接使用px進行開發,項目啓動或者部署後,會直接按照比例轉換爲remgithub
postcss.config.jsweb
module.exports = { plugins: { "autoprefixer": { browsers: ['Android >= 4.0', 'iOS >= 7'] }, "postcss-pxtorem": { "rootValue": 37.5, // 設計稿寬度的1/10, "propList": ['*']// 須要作轉化處理的屬性,如`hight`、`width`、`margin`等,`*`表示所有 } } };
package.json
增長postcss-pxtorem的依賴,而後npm install
三,使用UI vant進行快速項目開發
1,安裝babel-plugin-import依賴
2,在.babelrc 或者 babel.config.js文件裏面加入如下配置
babel7版本以上配置:
module.exports = {
presets: ["@vue/app"], plugins: [ ['import', { libraryName: 'vant', libraryDirectory: 'es', style: true }, 'vant'] ] };
babel7版本如下配置:
{ "plugins": [ ["import", { "libraryName": "vant", "libraryDirectory": "es", "style": true }] ] }
3,在項目中引入直接使用
import { Button } from 'vant';
具體vant使用參考官網
四,api請求axios、jsonp、util等插件封裝
1,axios、jsonp請求統一封裝爲httpRequest.js
import axios from "axios"; import jsonp from "jsonp"; // 請求攔截器 axios.interceptors.request.use( config => { return config; }, error => { return Promise.reject(error); } ); // 返回攔截器 axios.interceptors.response.use( response => { return response; }, error => { return Promise.resolve(error.response); } ); class HttpRequest { get(url, paramer, header) { return this.post(url, paramer, header, "get"); } /** * url : 請求地址 * param : 請求參數 * header : 須要添加的header,例如:{"Authorization":"xxxxx"} * json: "application/json; charset=utf-8" * form: "application/x-www-form-urlencoded; charset=utf-8" */ post(url, params, header, method) { let headers = { "Content-Type": "application/json" }; if (header) { Object.assign(headers, header); } let data = new Promise((resolve, reject) => { axios .request({ url: url, method: method ? "get" : "post", params: method == "get" ? params : null, data: method != "get" ? params : null, headers: headers, timeout: 10000, responseType: "json" }) .then(response => { resolve(response["data"]); }) .catch(function(error) { reject(error); }); }); return data; } /** * url:請求地址 * pm:服務端接收jsonp的名稱,默認爲jsoncallback * 注:callback爲服務端返回的函數名稱 */ jsonp(url, pm) { const data = new Promise((resolve, reject) => { jsonp( url, { timeout: TIMEOUT, param: pm === true ? pm : "jsoncallback", name: "callback" }, (err, data) => { if (err) { reject(err); } else { resolve(data); } } ); }); return data; } } export default new HttpRequest();
2,業務service統一封裝爲httpService.js
import HttpRequest from "@/service/httpRequest.js"; import { URL, CTS } from "@/config/config.js"; import { getLocal } from "@/util/util.js"; class HttpService { // 2.1校驗用戶信息 checkInfo(cusName, certCode, phone) { return HttpRequest.post(URL.kdUrl + "/queryPhone", { openid: this.getOpenId(), cusName: cusName, certCode: certCode, phone: phone }); } // 2.2查詢用戶寬帶信息 fetchAccount(type, cusName) { return HttpRequest.post(URL.kdUrl + "/queryAccount", { openid: this.getOpenId(), cusName: cusName, type: type }); } // 獲取openId getOpenId() { return getLocal('OPENID'); } } export default new HttpService();
3,全局配置項封裝爲config.js
// 接口地址配置 export const URL = { kdUrl: "http://xxx:8080/portal", }; // 常量配置 export const CTS = { // 是否開啓mock模擬數據 MOCK_FLG: false, // 是否開啓日誌打印 CONSOLE_FLG: true, // aes加密祕鑰 AES_KEY: "xxx" }; // http請求超時時間 單位:s export const TIMEOUT = "10000";
4,工具類util.js
import CryptoJS from "crypto-js"; export const oidInit = () => { try{ let url = window.location.href; url = url.substring(0,url.indexOf("?")) + '?oid=true'; window.history.pushState(null, null, url) }catch(e){ //TODO handle the exception } }; /** * 存儲localStorage */ export const setLocal = (name, content) => { if (!name) return; if (typeof content !== "string") { content = JSON.stringify(content); } if (window.localStorage) { window.localStorage.setItem(name, content); } }; /** * 獲取localStorage */ export const getLocal = name => { if (!name) return; if (!window.localStorage) return; return window.localStorage.getItem(name); }; /** * 刪除localStorage */ export const removeLocal = name => { if (!name) return; if (!window.localStorage) return; window.localStorage.removeItem(name); }; /** * 存儲sessionStorage */ export const setSession = (name, content) => { if (!name) return; if (typeof content !== "string") { content = JSON.stringify(content); } window.sessionStorage.setItem(name, content); }; /** * 獲取localStorage */ export const getSession = name => { if (!name) return; return window.sessionStorage.getItem(name); }; /** * 刪除localStorage */ export const removeSession = name => { if (!name) return; window.sessionStorage.removeItem(name); }; /** * 獲取style樣式 */ export const getStyle = (element, attr, NumberMode = "int") => { let target; if (attr === "scrollTop") { target = element.scrollTop; } else if (element.currentStyle) { target = element.currentStyle[attr]; } else { target = document.defaultView.getComputedStyle(element, null)[attr]; } return NumberMode === "float" ? parseFloat(target) : parseInt(target); }; /** * 判斷是不是微信 */ export const isWeiXin = () => { var ua = window.navigator.userAgent.toLowerCase(); if (ua.match(/MicroMessenger/i) === "micromessenger") { return true; } else { return false; } }; /** * 判斷是不是qq */ export const isQQ = () => { var ua = window.navigator.userAgent.toLowerCase(); if (ua.indexOf("qq/") > -1) { return true; } else { return false; } }; /** * 動態加載css */ export const loadCss = url => { var script = document.createElement("link"); script.rel = "stylesheet"; script.href = url; document.body.appendChild(script); }; /** * 動態加載js */ export const loadJs = url => { var script = document.createElement("script"); script.type = "text/javascript"; script.src = url; document.body.appendChild(script); }; /** * 獲取url連接裏面傳過來的值 * name:key的名稱 */ export const UrlVal = name => { var url = window.location.search.substr(1); if (window.location.search.substr(1).match("&")) { url = window.location.search.substr(1).replace(/&/g, "&"); } var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); var r = url.match(reg); if (r != null) return decodeURI(r[2]); return null; }; /** * 判斷當前設備是否爲ios */ export const isIos = () => { var ua = navigator.userAgent.toLowerCase(); if (/iphone|ipad|ipod/.test(ua)) { return true; } else if (/android/.test(ua)) { return false; } }; /** * 格式化當前時間 */ export const format = (date, fmt) => { var o = { "M+": date.getMonth() + 1, "d+": date.getDate(), "h+": date.getHours(), "m+": date.getMinutes(), "s+": date.getSeconds(), "q+": Math.floor((date.getMonth() + 3) / 3), S: date.getMilliseconds() }; if (/(y+)/.test(fmt)) { fmt = fmt.replace( RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length) ); } for (var k in o) { if (new RegExp("(" + k + ")").test(fmt)) { fmt = fmt.replace( RegExp.$1, RegExp.$1.length === 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length) ); } } return fmt; }; /** * 獲取當前時間戳 * 如:20170502102317 */ export const MakeTime = () => { let d = new Date(); let en = d.getFullYear() + "-" + (d.getMonth() + 1) + "-" + d.getDate(); let en1 = buLing(d.getHours()) + "" + buLing(d.getMinutes()) + "" + buLing(d.getSeconds()); return toDate(en).replace(/-/g, "") + en1; }; export const buLing = str => { if (str < 10) { str = "0" + str; } return str; }; export const toDate = time => { var arys = []; arys = time.split("-"); var fullyear = arys[0]; var month = arys[1]; var day = arys[2]; var date = ""; date += fullyear + "-"; if (month >= 10) { date += month + "-"; } else { date += "0" + month + "-"; } if (day >= 10) { date += day; } else { date += "0" + day; } return date; }; /** * aes加密 */ export const encodePwd = (data, key) => { var keyHex = CryptoJS.enc.Utf8.parse(key); var encrypted1 = CryptoJS.AES.encrypt(data, keyHex, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }); return CryptoJS.enc.Hex.parse(encrypted1.ciphertext.toString()).toString(); }; /** * aes解密 */ export const decodePwd = (data, key) => { var keyHex = CryptoJS.enc.Utf8.parse(key); var decrypted = CryptoJS.AES.decrypt( { ciphertext: CryptoJS.enc.Hex.parse(data.toString()) }, keyHex, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 } ); return decrypted.toString(CryptoJS.enc.Utf8); }; /** * Base64轉碼 */ export const encodeBase64 = data => { var str = CryptoJS.enc.Utf8.parse(data); return CryptoJS.enc.Base64.stringify(str); }; /** * Base64解碼 */ export const decodeBase64 = data => { var str = CryptoJS.enc.Base64.parse(data); return CryptoJS.enc.Utf8.stringify(str); }; /* * 日誌打印 */ export const Log = { isConsole: true, i: function(jsName, content) { if (this.isConsole) { console.info("位置:", content); } }, w: function(jsName, content) { if (this.isConsole) { console.warn("位置:", content); } }, e: function(jsName, content) { if (this.isConsole) { console.error("位置:", content); } } }; /* * 生成uuid */ export const uuid = () => { var s = []; var hexDigits = "0123456789abcdef"; for (var i = 0; i < 36; i++) { s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); } s[14] = "4"; s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); s[8] = s[13] = s[18] = s[23] = "-"; var uuid = s.join(""); return uuid; };
5,全局配置文件,供部署人員使用
注:正常項目上線的時候,會把build後的cli項目發給系統部署人員,他們須要根據不一樣的環境修改一下API的請求地址等參數,因此須要暴露出來一個配置文件,讓部署人員進行配置。
window.MURL = { SNOW_URL: "http://192.168.3.171:8080/videoApi" };
<script src="./config.js"></script>
window.MURL.SNOW_URL
GitHub示例地址 vue-ht-cli