在咱們平常開發過程當中,咱們本身常常會寫大量的方法,也就是function
,來封裝一些經常使用功能,來知足咱們的開發須要。本篇文章呢,我把本身這幾年前端開發寫的一些可複用的方法分享出來,與你們一塊兒學習探討:前端
衆所周知js的typeOf
或者instanceof
在數據類型檢測上都有侷限性,該方法檢測返回值是以字符串形式: [object String],[object Array],[object Function],[object Object],[object Null],[object RegExp],[object Undefined],[object Symbol]
`android
function dataType (type){ // 檢測數據類型
var dataType = Object.prototype.toString;
return dataType.call(type)
}
複製代碼
`ios
咱們平常開發中,數據多數是後端返回來的,咱們對因而否有返回來數據作相應的處理,該方法接收一個參數data,返回一個布爾值,是否爲空數據,true爲空,false爲否: `es6
function isEmpty(data){ //是否爲空數據
//null,undefined,'',"",{},[],[{}] 匹配到這些值時,都是返回true
if(data==='' || data==="" || data==='undefined' || data===undefined || data===null)
{return true}
if(JSON.stringify(data)=='{}' || JSON.stringify(data)=='[]' || JSON.stringify(data)=='[{}]')
{return true}
return false
複製代碼
} `web
多維數組指的是咱們處理的數據裏,數組裏面還嵌套有數組,有時候咱們的代碼邏輯須要不數組拉伸維一維的數組來處理,這就是此方法的做用了,該方法只接受一個參數,該參數就是個數組,返回也是個數組: `element-ui
var arry = [11, 7, 5, [1, 9], 3, [15, [13, 17]]];
function flattenDepth(arry){
let result = [];
arry.map(item => {
if (Array.isArray(item)) { // es6語法檢測當前是不是數組
result.push(...flattenDepth(item)) // 此處是用了es6語法,擴展運算符
} else {
result.push(item)
}
})
return result;
}
複製代碼
`json
對url的解析,咱們的主要目的都是獲取url上的參數,也就是query值,該方法接收一個url參數,會返回一個參數對象: `canvas
function queryUrl(url) { // 解析url數據傳參
var objUrl = {};
var urlData = url.split('?')[1];
if (urlData) {
var urlArr = urlData.split('&');
for (var i = 0, len = urlArr.length; i < len; i++) {
var curArr = urlArr[i].split('=');
objUrl[curArr[0]] = curArr[1]
}
return objUrl
}
}
複製代碼
`後端
轉千位符是咱們對數字處理的一個方法,該方法接收一個數字: `數組
function toThousands1(num) { //轉千位符 方法1
var num = Number(num).toFixed(2);
var n = num.indexOf('.');
var str1 = num.slice(0, n), str2 = num.slice(n, num.length), result = '';
while (str1.length > 3) {
result = ',' + str1.slice(-3) + result;
str1 = str1.slice(0, str1.length - 3);
}
if (str1) { result = str1 + result; }
return result+str2;
}
function toThousands2(num) { // 轉千位符 方法2
var num = Number(num).toFixed(2); //若是你想把你轉的數保留3位小數,把2改3就行了
var n = num.indexOf('.');
var str1 = num.slice(0, n), str2 = num.slice(n, num.length);
var result = '', counter = 0;
for (var i = str1.length - 1; i >= 0; i--) {
counter++;
result = str1.charAt(i) + result;
if (!(counter % 3) && i != 0) { result = ',' + result; }
}
return result+str2;
}
複製代碼
`
對數字轉大寫,特別是開發金融類型的web或者h5時,使用最多,該方法接收一個參數,就是要轉的數字, `
function convertCurrency(money) { // 金額數字轉大寫
//漢字的數字
var cnNums = new Array('零', '壹', '貳', '叄', '肆', '伍', '陸', '柒', '捌', '玖');
//基本單位
var cnIntRadice = new Array('', '拾', '佰', '仟');
//對應整數部分擴展單位
var cnIntUnits = new Array('', '萬', '億', '兆');
//對應小數部分單位
var cnDecUnits = new Array('角', '分', '毫', '釐');
//整數金額時後面跟的字符
var cnInteger = '整';
//整型完之後的單位
var cnIntLast = '元';
//最大處理的數字
var maxNum = 999999999999999.9999;
//金額整數部分
var integerNum;
//金額小數部分
var decimalNum;
//輸出的中文金額字符串
var chineseStr = '';
//分離金額後用的數組,預約義
var parts;
if (money == '') { return ''; }
money = parseFloat(money);
if (money >= maxNum) {
//超出最大處理數字
return '';
}
if (money == 0) {
chineseStr = cnNums[0] + cnIntLast + cnInteger;
return chineseStr;
}
//轉換爲字符串
money = money.toString();
if (money.indexOf('.') == -1) {
integerNum = money;
decimalNum = '';
} else {
parts = money.split('.');
integerNum = parts[0];
decimalNum = parts[1].substr(0, 4);
}
//獲取整型部分轉換
if (parseInt(integerNum, 10) > 0) {
var zeroCount = 0;
var IntLen = integerNum.length;
for (var i = 0; i < IntLen; i++) {
var n = integerNum.substr(i, 1);
var p = IntLen - i - 1;
var q = p / 4;
var m = p % 4;
if (n == '0') {
zeroCount++;
} else {
if (zeroCount > 0) {
chineseStr += cnNums[0];
}
//歸零
zeroCount = 0;
chineseStr += cnNums[parseInt(n)] + cnIntRadice[m];
}
if (m == 0 && zeroCount < 4) {
chineseStr += cnIntUnits[q];
}
}
chineseStr += cnIntLast;
}
//小數部分
if (decimalNum != '') {
var decLen = decimalNum.length;
for (var i = 0; i < decLen; i++) {
var n = decimalNum.substr(i, 1);
if (n != '0') {
chineseStr += cnNums[Number(n)] + cnDecUnits[i];
}
}
}
if (chineseStr == '') {
chineseStr += cnNums[0] + cnIntLast + cnInteger;
} else if (decimalNum == '') {
chineseStr += cnInteger;
}
return chineseStr;
}
複製代碼
`
js動畫是咱們前端開發最常接觸的功能之一,雖然市面上有不少成熟的動畫框架,可是有時候咱們只是一個小功能,沒有必要引入那些庫的時候,那麼這個方法就足夠你使用了: `
//js運動框架,四個參數,第一個要運動的元素,第二,要變化的值,注意此處是個json對象,第三個是要運動的速度,第四個是鏈式運動的函數
function cartoon(el, json, s, fn) {
clearInterval(el.timer); //開啓定時器前線清除上個定時器
el.timer = setInterval(function () { //開啓一個定時器
var isStop = true;
for (var attr in json) { //循環參數裏的json對象
var curStyle = null; //聲明一個空對象,用來存儲當前元素的值
if(attr == 'opacity'){ //若是參數是opacity,表示要改變透明度的變化
curStyle = Math.round(parseFloat(getCss(el, attr))*100); //parseFloat是保留小數,Math.round是四捨五入
//之因此要用Math.round,就是考慮getCss取出來的數會有小數,因此讓他四捨五入
} else {
curStyle = parseInt(getCss(el, attr)); //parseInt是取整
}
var speed = (json[attr] - curStyle) / s; //計算速度
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); //若是speed大於0就向上取整,小於0向下取整
if (curStyle != json[attr]) { //若是當前元素的值沒有等於目標值
isStop = false; //把isStop設置爲false
}
if (attr == 'opacity') { //若是屬性爲opacity透明度,則單獨設置屬性
el.style[attr] = (curStyle + speed) / 100;
el.style.filter = 'alpha(opacity:'+(curStyle+speed)+')';
} else { //不是的採用原來設置的方式
el.style[attr] = curStyle + speed + 'px';
}
if (isStop) { //只有isStop爲true,才中止定時器
clearInterval(el.timer);
if (fn) fn(); //判斷用戶有沒有傳入鏈式函數
}
}
}, 30)
}
function getCss(el, attr) { // 這個是取元素樣式的公共方法
if (el.currentStyle) {
return el.currentStyle[attr];
} else {
return getComputedStyle(el, null)[attr];
}
}
複製代碼
`
圖片壓縮的功能,在移動端開發的應用上會較多,由於流量就是金錢,咱們要爲用戶省錢呀,最典型的圖片壓縮場景就是上傳頭像,你不可能自拍個10幾MB的上傳吧,那麼試試這個方法吧:該方法是結合input
標籤的file
類型使用的,接收兩個參數,第一個是事件對象,第二個是個回調函數,回調函數的參數裏能夠拿到你須要的數據: `
function compressImg (event, callback) { // callback回調函數帶一個對象參數
// 選擇的文件對象(file裏只包含圖片的體積,不包含圖片的尺寸)
var file = event.target.files[0];
// 選擇的文件是圖片
if(file.type.indexOf("image") === 0) {
// 壓縮圖片須要的一些元素和對象
var reader = new FileReader(),
img = new Image();
reader.readAsDataURL(file);
// 文件base64化,以便獲知圖片原始尺寸
reader.onload = function(e) {
img.src = e.target.result;
};
// base64地址圖片加載完畢後執行
img.onload = function () {
// 縮放圖片須要的canvas(也能夠在DOM中直接定義canvas標籤,這樣就能把壓縮完的圖片不轉base64也能直接顯示出來)
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
// 圖片原始尺寸
var originWidth = this.width;
var originHeight = this.height;
// 最大尺寸限制,可經過設置寬高來實現圖片壓縮程度
var maxWidth = 1920,
maxHeight = 1080;
var targetWidth = originWidth,
targetHeight = originHeight;
if(originWidth > maxWidth || originHeight > maxHeight) {
if(originWidth / originHeight > maxWidth / maxHeight) {
targetWidth = maxWidth;
targetHeight = Math.round(maxWidth * (originHeight / originWidth));
} else {
targetHeight = maxHeight;
targetWidth = Math.round(maxHeight * (originWidth / originHeight));
}
}
// canvas對圖片進行縮放
canvas.width = targetWidth;
canvas.height = targetHeight;
// 清除畫布
context.clearRect(0, 0, targetWidth, targetHeight);
// 圖片壓縮
context.drawImage(img, 0, 0, targetWidth, targetHeight);
/*第一個參數是建立的img對象;第二三個參數是左上角座標,後面兩個是畫布區域寬高*/
//壓縮後的圖片轉base64 url
/*canvas.toDataURL(mimeType, qualityArgument),mimeType 默認值是'image/png';
* qualityArgument表示導出的圖片質量,只有導出爲jpeg和webp格式的時候此參數纔有效,默認值是0.92*/
var newUrl = canvas.toDataURL('image/jpeg', 0.75);//base64 格式
let obj = {imgSrc: newUrl}
//也能夠把壓縮後的圖片轉blob格式用於上傳
canvas.toBlob((blob) => {
obj.blob = blob;
callback(obj);
}, 'image/jpeg', 0.75)
};
} else {
console.log('請選擇你的圖片')
}
}
compressImg(event, function(data){ // 使用
console.log(data)
})
複製代碼
`
檢測瀏覽器類型這個方法,主要在移動端作h5開發會用的較多,由於咱們並不知道用戶用什麼手機,用什麼瀏覽,而咱們的代碼邏輯也須要作相應的處理,此方法就是用來判斷瀏覽器類型的,該方法能夠返回個布爾值: `
var browser = {
versions:function(){
var u = window.navigator.userAgent; // 經過navigator.userAgent獲取當前瀏覽器的信息
return {
trident: u.indexOf('Trident') > -1, //IE內核
presto: u.indexOf('Presto') > -1, //opera內核
webKit: u.indexOf('AppleWebKit') > -1, //蘋果、谷歌內核
gecko: u.indexOf('Firefox') > -1, //火狐內核
mobile: !!u.match(/AppleWebKit.*Mobile.*/)||!!u.match(/AppleWebKit/), //是否爲移動終端
ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios終端
android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android終端或者uc瀏覽器
iPhone: u.indexOf('iPhone') > -1 || u.indexOf('Mac') > -1, //是否爲iPhone或者安卓QQ瀏覽器
iPad: u.indexOf('iPad') > -1, //是否爲iPad
webApp: u.indexOf('Safari') == -1 ,//是否爲web應用程序,沒有頭部與底部
weixin: u.indexOf('MicroMessenger') == -1 //是否爲微信瀏覽器
};
}()
}
console.log(browser.versions.trident) // 檢測是否爲IE瀏覽器
console.log(browser.versions.webKit) // 檢測是否爲谷歌瀏覽器
複製代碼
`
所謂樹數據,其實我指的就是咱們平常開發中處理的那些樹形結構,通常後臺只會返回一個數組的數據,須要咱們處理他的數據層級結構,並顯示在咱們的組件上去,例如element-ui的el-tree樹組件: `
let data = [
{id: 1, value: '動物'}, {id: 2, value: '植物'}, {id: 3, value: '微生物'}, {id: 4, value: '無機物'},
{id: 5, parentId: 1, value: '脊椎類動物'}, {id: 6, parentId: 2, value: '木科植物'}, {id: 7, parentId: 1, value: '無脊椎類動物'}, {id: 8, parentId: 2, value: '草本植物'},
{id: 9, parentId: 3, value: '細菌'}, {id: 10, parentId: 5, value: '老虎'}, {id: 11, parentId: 5, value: '獅子'}, {id: 12, parentId: 5, value: '獵豹'},
{id: 13, parentId: 6, value: '松樹'}, {id: 14, parentId: 6, value: '樟樹'}, {id: 15, parentId: 6, value: '樺樹'}, {id: 16, parentId: 7, value: '蝦'},
{id: 17, parentId: 7, value: '章魚'}, {id: 18, parentId: 3, value: '真菌'}, {id: 19, parentId: 3, value: '病毒'}, {id: 20, parentId: 4, value: '黃金'},
{id: 21, parentId: 8, value: '牡丹花'}, {id: 22, parentId: 8, value: '四葉草'}, {id: 23, parentId: 4, value: '白銀'}, {id: 24, parentId: 4, value: '玉石'},
{id: 25, parentId: 4, value: '珍珠'}, {id: 26, parentId: 9, value: '球狀桿菌'}
]
function classify (arr) { // 樹數據遞歸處理函數
let first = [], others = [];
arr.forEach(item => {
item.children = [];
if (!item.parentId) {
first.push(item)
} else {
others.push(item)
}
});
function recursion (arr, ary) {
arr.forEach(item => {
let other = []
ary.map(cur => {
if (item.id === cur.parentId) {
item.children.push(cur)
} else {
other.push(cur)
}
})
recursion(item.children, other);
})
}
recursion(first, others);
return first;
}
let ary = classify(data);
複製代碼
` 注意:該方法拿過去後,須要把你數據裏的關鍵字段作個替換,由於通常的樹數據都有當前數據的id和歸屬哪一個父數據下的一個parentId,我這裏只是作的模擬,並不肯定你的數據也是這個字段名稱,你須要找到你的關鍵字段替換就OK。
該方法在咱們開發抽取隨機幸運觀衆,隨機禮品那種功能的時候應用較多,該方法接收兩個參數,一個正整數類型的參數,一個取多少個隨機數,會返回一個數組,數組裏是隨機的數字: `
function getRandom(integer, size) {
let arr = [];
function count() {
if (arr.length < size) {
let n = Math.round(Math.random() * integer);
if(!arr.includes(n)) {
arr.push(n)
}
count()
}
}
count()
return arr
}
getRandom(100, 10) // 隨機取出0-100之內10位數字
複製代碼
`
加密的功能通常來講是先後端都須要作的,前端也會用啥md5加密之類的工具,此方法應用的場所只是針對咱們有些普通的數據,例如存儲在localStorage這些數據,咱們不但願他這麼直白的顯示在那,咱們就須要對他作個加密處理,這裏包含兩個方法,一個加密,一個解密,都須要一個字符串參數:
`
function compileStr (code) { // 對字符串進行加密
var c = String.fromCharCode(code.charCodeAt(0) + code.length);
for(var i = 1; i < code.length; i++){
c += String.fromCharCode(code.charCodeAt(i) + code.charCodeAt(i - 1));
}
return escape(c);
}
function uncompileStr (code) { // 字符串進行解密
code = unescape(code);
var c = String.fromCharCode(code.charCodeAt(0)-code.length);
for(var i = 1; i < code.length; i++){
c += String.fromCharCode(code.charCodeAt(i) - c.charCodeAt(i - 1));
}
return c;
}
複製代碼
` 注意:該方法的加密規則,你能夠自行變化下,保證能夠作到即使是拷貝同一份代碼,大家的加解密的方式也不一樣。
倒計時是咱們前端開發較常見的功能需求之一了,例如商品列表的倒計時,啥啥活動倒計時,節日倒計時,本示例以節日倒計時爲例演示,略微修改你就能夠改爲任何你想要的倒計時了,該方法接收一個參數,就是目標時間字符串: `
function countDown (targetDate) { // 參數targetDate是目標時間
var targetDateMs = Date.parse(targetDate); // 目標時間毫秒數
var myDate = new Date()
var curDateMs = Date.now(); // 獲取當前時間毫秒數 方法1
// var curDateMs = Date.parse(myDate) // 獲取當前時間的毫秒數 方法2
if (curDateMs != targetDateMs) { // 當前時間只要不等於目標時間毫秒數
var timeDifference = targetDateMs-curDateMs; // 當前時間與目標時間的時間差毫秒數
var monthTotalMs = 1000 * 60 * 60 * 24 * 30; // 月毫秒總數
var dayTotalMs = 1000 * 60 * 60 * 24; // 1天毫秒總數
var hoursTotalMs = 1000 * 60 * 60; // 1小時毫秒總數
var minutesTotalMs = 1000 * 60; // 1分鐘毫秒總數
var month = Math.floor(timeDifference / monthTotalMs); //計算月
var surplusDayMs = timeDifference - (month * monthTotalMs); // 計算減去月後剩餘的毫秒數
var day = Math.floor(surplusDayMs / dayTotalMs); // 計算天
var surplusHoursMs = surplusDayMs - (day * dayTotalMs); // 計算減去天后剩餘的毫秒總數
var hours = Math.floor(surplusHoursMs / hoursTotalMs); // 計算小時
var surplusMinutesMs = surplusHoursMs - (hours * hoursTotalMs); // 計算減去小時後還剩餘的毫秒總數
var minutes = Math.floor(surplusMinutesMs / minutesTotalMs);// 計算分
var seconds = Math.ceil((surplusMinutesMs - (minutes * minutesTotalMs)) / 1000); //剩餘多少秒
return `距離2019年倒計時:${month}月${day}天${toDou(hours)}時${toDou(minutes)}分${toDou(seconds)}秒`
} else { // 等於就中止計時器
clearInterval(time);
}
}
function toDou(n){ // 用於補0的方法
if(n<10){
return '0'+n;
}else{
return ''+n;
}
}
var time = setInterval(function(){
document.querySelector('.div-date').innerText = countDown ('2020-01-01');
}, 1000)
複製代碼
`
本章節的多數方法都是能夠能夠直接拿來使用的,個別方法須要根據你本身具體需求略微小改就OK了,固然這裏的這些方法都是以我過往的業務需求寫的,也許與你的需求有些差別,只要功能類似,我相信調整一下都是能夠實現的,本章節後續會繼續補充,各位大佬要是也有啥實用的公共小方法也能夠共享一下,謝謝。