在咱们平常开发过程当中,咱们本身常常会写大量的方法,也就是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了,固然这里的这些方法都是以我过往的业务需求写的,也许与你的需求有些差别,只要功能类似,我相信调整一下都是能够实现的,本章节后续会继续补充,各位大佬要是也有啥实用的公共小方法也能够共享一下,谢谢。