Vue技术点整理-Vue CLI
Vue CLI 是一个基于 Vue.js 进行项目快速开发的脚手架
注:具体安装步骤可参考Vue CLI,默认安装的脚手架,是没有service、util等工具类的,以下主要描述如何在脚手架的基础上进行快速开发
GitHub示例地址 vue-ht-cli
一,vue.config.js配置文件
默认Vue CLI安装完成后,是没有这个配置文件的,需要手动在项目根目录创建,并修改使用:
以下为我简单配置的文件,更多详细配置,请参考 Vue CLI官网
vue.config.js
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 } };
设置代理模式
devServer: { proxy: { '/api': { target: '<url>', ws: true, changeOrigin: true }, '/foo': { target: '<other_url>' } } }
二,使用postcss-pxtorem自动px转换为rem
注:根据UI设计稿的比例(750、375等),设置rootValue的值
开发时直接使用px进行开发,项目启动或者部署后,会直接按照比例转换为rem
postcss.config.js
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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 接口地址配置 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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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的请求地址等参数,所以需要暴露出来一个配置文件,让部署人员进行配置。
- 在pubic目录下面,创建一个config.js
window.MURL = { SNOW_URL: "http://192.168.3.171:8080/videoApi" };
- 修改当前目录下的index.html模板,引入config.js
<script src="./config.js"></script>
- 然后在项目中即可使用全局变量
window.MURL.SNOW_URL
- npm run build 以后,生成目录为以下:
GitHub示例地址 vue-ht-cli