js常用的一些自定义函数、方法

/**
 * @function 判断数据类型
 * @param {any} o 对应的数据
 * @example
 * types("") // "string"
types({}); // "object"
types([]); // "array"
types(100); // "number"
types(null); // "null"
types(); // "undefined"
types(/abcd/); // "regex"
types(new Date()); // "date"
 * 
 */
const types = (o) => {
  var s = Object.prototype.toString.call(o);
  return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};


/**
* @function 获取浏览器地址的参数
* @param {String} [name=''] 获取值的key,默认为空,为空时,函数返回json对象
* @param {String} [url=window.location.href] 地址,默认为浏览器的url
* @example  getParams('aa', 'https://www.baidu.com?aa=101')       //101
*/
const getParams = (name = '', url = window.location.href) => {
  let endVal = '';
  if (url.indexOf("?") != -1) {   //判断url中有没有出现?
    let arrs = url.substring(url.indexOf("?") + 1).split('&');  //截取字符串,获取到?后面的那部分内容;以&符号为准,分割成数组
    arrs = arrs.filter(item => item);     //原有数组过滤为空的值
    let obj = {};
    for (let i = 0; i < arrs.length; i++) {
      let index = arrs[i].indexOf("=");
      let keys = arrs[i].substring(0, index);       //第一个等号前面的那部分
      let vals = arrs[i].substring(index + 1);      //第一个等号后面的内容
      obj[keys] = decodeURI(vals);    //解码输出,值含有中文字符的情况
    }
    if (arrs.length > 0) {  //先判断数组是不是为空,在判断name是不是有值传过来
      if (name) {
        endVal = obj[name] || '';
      } else {
        endVal = obj;
      }
    }
  }
  return endVal;
}


/**
 * @function 地址栏追加参数,不刷新页面,不增加历史记录
 * @param {String} key 参数的名称
 * @param {String|*} value 参数的值
 * @param {String} url 地址,使用的是浏览器的当前地址
 */
const updateQueryStringParameter = (key, value, url = window.location.href) => {
  let re, separator, newurl;
  if (!key || !value) {
    newurl = url;
  }
  re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
  separator = url.indexOf('?') !== -1 ? "&" : "?";
  if (url.match(re)) {
    newurl = url.replace(re, '$1' + key + "=" + value + '$2');
  }
  else {
    newurl = url + separator + key + "=" + value;
  }
  //向当前url添加参数,没有历史记录
  window.history.replaceState({
    path: newurl
  }, '', newurl);

}




/**
* @function 防抖函数,规定时间内点击多次,只执行最后一次
* @method debounce(fn,delay);
* @param {function} fn       需要执行的函数
* @param {number} [delay=300]     等待时间(毫秒),默认等待时间为300毫秒,为0的话就不需要防抖函数了
* @example 
  const func = () => {
      console.log("1234567");
  };
  const dianji = debounce(func, 500);
*/
const debounce = (fn, delay = 300) => {
  let timer = null; // 创建一个标记用来存放定时器的返回值
  return function () {
    // 再次执行的时候把前一个 setTimeout clear 清空掉
    clearTimeout(timer);
    // 然后又创建一个新的 setTimeout, 这样就能保证interval 间隔内如果时间持续触发,就不会执行 fn 函数
    timer = setTimeout(() => {
      fn.apply(this, arguments);
    }, delay);
    // timer = setTimeout(fn, delay) // 简化写法
  };
}

/**
* @function 节流函数,连续点击多次,规定时间内只执行一次
* @method throttle(fn,delay);
* @param {function} fn       需要执行的函数
* @param {number} [delay=300]     等待时间(毫秒),默认等待时间为300毫秒
* @example 
  const func = (aa) => {
      console.log(aa);
  };
  const dianji = throttle(()=>{func("12345")}, 500);
*/
const throttle = (fn, delay = 300) => {
  let timer = null; // 创建一个标记用来存放定时器的返回值
  return function () {
    // 在函数开头判断timer标记是否为null,只有为null时才让他执行一次里面的函数
    if (!timer) {
      // 将外部传入的函数的执行放在setTimeout中
      timer = setTimeout(() => {
        // 调用传入的函数fn
        // 最后在setTimeout执行完毕后再把标记timer设置为null,表示可以执行下一次循环了。
        fn.apply(this, arguments);    //或者使用fn()
        timer = null;
      }, delay);
    }
  };
}


/** 
* @description 时间戳转化为年 月 日 时 分 秒 
* @method formatTime(num,format)
* @param {number} [num = new Date().getTime()] 时间戳,默认使用当前时间戳, new Date().getTime(); 获取当前时间戳(毫秒)
* @param {string} [format='YYYY-mm-dd HH:MM:SS'] 时间格式 默认'YYYY-mm-dd HH:MM:SS' ,更改只需替换中间连接符号就行'YYYY年mm月dd日 HH时MM分SS秒'
* @example 
* var sjc = 1472048779952; //js一般获取的时间戳是13位,PHP一般是10位
* formatTime(sjc, 'YYYY-mm-dd HH:MM:SS')
*/
const formatTime = (num = new Date().getTime(), format = "YYYY-mm-dd HH:MM:SS") => {
  let ret, date, renum;
  // 处理时间戳,js一般获取的时间戳是13位,PHP一般是10位,根据实际情况做判断处理
  if (num.toString().length == 10) {
    date = new Date(parseInt(num) * 1000);
  } else if (num.toString().length == 13) {
    date = new Date(parseInt(num));
  } else {
    date = new Date(parseInt(num));
  }
  const opt = {
    "Y+": date.getFullYear().toString(), // 年
    "m+": (date.getMonth() + 1).toString(), // 月
    "d+": date.getDate().toString(), // 日
    "H+": date.getHours().toString(), // 时
    "M+": date.getMinutes().toString(), // 分
    "S+": date.getSeconds().toString() // 秒
    // 目前用的是这六种符号,有其他格式化字符需求可以继续添加,必须转化成字符串
  };
  for (var k in opt) {
    ret = new RegExp("(" + k + ")").exec(format);
    if (ret) {
      renum = (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")) //根据复数前面是否补零,如“mm”补零,单“m”前面不补零
      format = format.replace(ret[1], renum)
    };
  };
  return format;
};


/**
* @function 发布时间显示函数
* @method timeFormat(time)
* @param {number} time 时间戳(必填)
* @example  var text=timeFormat(1472048779952);
@ 1、< 60s, 显示为“刚刚”
@ 2、>= 1min && < 60 min, 显示与当前时间差“XX分钟前”
@ 3、>= 60min && < 1day, 显示与当前时间差“今天 XX:XX”
@ 4、>= 1day && < 1year, 显示日期“XX月XX日 XX:XX”
@ 5、>= 1year, 显示具体日期“XXXX年XX月XX日 XX:XX”
*/
const timeFormat = (time) => {
  let date;
  if (time) {
    if (time.toString().length == 10) {
      date = new Date(parseInt(time) * 1000);
    } else if (time.toString().length == 13) {
      date = new Date(parseInt(time));
    } else {
      date = new Date(parseInt(time));
    }

    let curDate = new Date(),
      year = date.getFullYear(),
      month = date.getMonth() + 1,
      day = date.getDate(),
      hour = date.getHours(),
      minute = date.getMinutes(),
      curYear = curDate.getFullYear(),
      curHour = curDate.getHours(),
      timeStr;

    if (year < curYear) {
      timeStr = year + '年' + month + '月' + day + '日 ' + hour + ':' + minute;
    } else {
      let pastTime = curDate - date,
        pastH = pastTime / 3600000;

      if (pastH > curHour) {
        timeStr = month + '月' + day + '日 ' + hour + ':' + minute;
      } else if (pastH >= 1) {
        timeStr = '今天 ' + hour + ':' + minute + '分';
      } else {
        let pastM = curDate.getMinutes() - minute;
        if (pastM > 1) {
          timeStr = pastM + '分钟前';
        } else {
          timeStr = '刚刚';
        }
      }
    }
    return timeStr;
  }

}

/**
* @function 字符串截取、字符串替换(例如手机号、身份证等号码隐藏)
* @method strCut(str,start,len,rep)
* @param {string}  str	为去要截取的字符串(类型为字符串)
* @param {number}  start	为从第几位开始截取(不是下标)
* @param {number}  [len]	截取的长度(不填从开始截取到最后)
* @param {string}  [rep='']	需要替换的字符(例如:"*")默认为空
* @example  var value=strCut('18011223344',4,4,'*')
*/
const strCut = (str, start, len, rep = '') => {
  if (str && (str.length - start) > 0) {	//判断开始截取的位置,字符串的长度需大于截取的长度
    let repnum = '', strnum = '';
    if (len) {
      strnum = (str.length - start) > len ? len : (str.length - start);  //到最后能够替换字符的个数
    } else {
      strnum = str.length - start;
    }

    for (let i = 0; i < strnum; i++) {
      repnum += rep
    }
    let strre = str.substr(start - 1, len);	//截取(start-1)对应截取的位置
    let strend = str.replace(strre, repnum);	//替换
    return strend;
  } else {
    return str;
  }
}

/**
* @function 去除字符串左侧指定字符
* @method  ltrim(str,char)
* @param {string} str  需要去除指定字符的字符串
* @param {string} [char] 左侧需要去除的字符,(不填默认去除空格)
* @example ltrim("&&&1234a&11&&","&")    //1234a&11&&
*/
const ltrim = (str, char = '') => {
  let lstr = str.replace(new RegExp('^\\s+', 'g'), '');    //默认去除左侧空格
  if (char) {
    lstr = str.replace(new RegExp('^[' + char + ']+', 'g'), '');
  }
  return lstr;
}

/**
* @function 去除字符串右侧指定字符
* @method  rtrim(str,char)
* @param {string} str  需要去除指定字符的字符串
* @param {string} [char=''] 右侧需要去除的字符,(不填默认去除空格)
* @example rtrim("&&&1234a&11&&","&")    //&&&1234a&11
*/
const rtrim = (str, char = '') => {
  let rstr = str.replace(new RegExp('\\s+$', 'g'), '');   //默认去除右侧空格
  if (char) {
    rstr = str.replace(new RegExp('[' + char + ']+$', 'g'), '');
  }
  return rstr;
}

/**
* @function 去除字符串左右两边指定字符,直接调用上面ltrim()和rtrim()方法
* @method  trim(str,char)
* @param {string} str  需要去除指定字符的字符串
* @param {string} [char=''] 左侧需要去除的字符,(不填默认去除两边空格)
* @example trim("&&&1234a&11&&","&")    //1234a&11
*/
const trim = (str, char = '') => {
  let endstr = str.trim();    //默认去除左右两边空格
  if (char) {
    endstr = rtrim(ltrim(str, char), char);
  }
  return endstr;
}



/**
* 判断浏览器函数,判断用户是PC端、移动端
* @method isMobile()
*/
function isMobile() {
  if (window.navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) {
    return true;  // 移动端
  } else {
    return false;  // PC端
  }
}



/**
* 简单封装ajax,用于请求数据,未作跨域处理,
* 参数说明:
* @param {object} opts: {'可选参数'}
* @param {string} method: 请求方式:GET/POST,默认值:'GET';
* @param {string} url:    发送请求的地址, 默认值: 当前页地址;
* @param {any} data: 发送给后台的数据, string,json;
* @param {boolean} async: 是否异步:true/false,默认值:true;
* @param {boolean} cache: 是否缓存:true/false,默认值:true;
* @param {string} contentType: HTTP头信息,默认值:'application/x-www-form-urlencoded';
* @param {function} success: 请求成功后的回调函数;
* @param {function} error: 请求失败后的回调函数;
* @example 
  ajax({
    url: "http://poetry.apiopen.top/sentences",
    success: function (res) {
      console.log(res);
    },
  })
*/
const ajax = (opts) => {
  //一.设置默认参数
  var defaults = {
    method: 'GET',
    url: '',
    data: '',
    async: true,
    cache: true,
    contentType: 'application/x-www-form-urlencoded',
    success: function () { },
    error: function () { }
  };

  //二.用户参数覆盖默认参数,或者使用(es6扩展运算符):defaults={ ...defaults, ...opts };  
  for (var key in opts) {
    defaults[key] = opts[key];
  }

  //三.对数据进行处理
  if (typeof defaults.data === 'object') { //处理 data
    var str = '';
    for (var key in defaults.data) {
      str += key + '=' + defaults.data[key] + '&';
    }
    defaults.data = str.substring(0, str.length - 1);
  }

  defaults.method = defaults.method.toUpperCase(); //处理 method,统一转成大写,方便后面处理
  defaults.cache = defaults.cache ? '' : '&' + new Date().getTime(); //处理 cache

  if (defaults.method === 'GET' && (defaults.data || defaults.cache)) {
    defaults.url += '?' + defaults.data + defaults.cache; //处理 url 
  }


  //四.开始编写ajax
  //1.创建ajax对象
  var oXhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
  //2.和服务器建立联系,告诉服务器你要取什么文件
  oXhr.open(defaults.method, defaults.url, defaults.async);
  //3.发送请求
  if (defaults.method === 'GET')
    oXhr.send(null);
  else {
    oXhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); //post请求会变为charset=UTF-8形式,这里重新定义请求头
    oXhr.send(defaults.data);
  }


  //4.等待服务器回应
  oXhr.onreadystatechange = function () {
    if (oXhr.readyState === 4) {
      if (oXhr.status === 200) {
        var endData;
        try {
          endData = eval('(' + oXhr.responseText + ')');
        } catch (e) {
          endData = oXhr.responseText;
        }
        defaults.success.call(oXhr, endData);
      } else {
        defaults.error();
      }
    }
  };
}

/**
* @function 回到顶部
* @param {string} el 需要返回顶部的标签元素,默认是DOM页面
* @example goTop(".el-scrollbar .el-scrollbar__wrap")
*/
const goTop = (el) => {
  let timer = '';
  cancelAnimationFrame(timer);
  timer = requestAnimationFrame(function fn() {
    let oTop, dom;
    //需要重新获取元素、滚动条高度
    if (el) {
      dom = document.querySelector(el);
      oTop = dom.scrollTop;
    } else {
      dom = window;
      oTop = document.body.scrollTop || document.documentElement.scrollTop;
    }

    if (oTop > 0) {
      // dom.scrollTo(0, (oTop - 100));
      dom.scrollTo(0, (oTop - oTop / 10));
      dom.onmousewheel = function () { return false }
      timer = requestAnimationFrame(fn);
    } else {
      dom.onmousewheel = function () { return true }
      cancelAnimationFrame(timer);
    }
  });
}


/**
* @function 设置localStorage,思路:封装成一个json数据存进去,保存时间、过期时间、保存的数据
* @method setStorage(name)
* @param {string} name  保存数据的key值,必填
* @param {any} [value='']   需要保存的数据
* @param {number} [time=0]   过期时间,以毫秒为单位,默认永不过期
* @example setStorage("aa","123456",5000)
*/
const setStorage = (name, value = '', time = 0) => {
  time = isNaN(time - 0) ? 0 : time - 0;    //转换成数字,字符串类型的数字也转成数字
  time = time > 0 ? time : 0;     //有负数的情况

  let obj = {
    jm_save_value: value,
    jm_save_time: time,
    jm_save_startTime: new Date().getTime()//记录何时将值存入缓存,毫秒级
  }
  if (name) {
    localStorage.setItem(name, JSON.stringify(obj));
  } else {
    console.log("请先设置name名");
  }
}

/**
* @function 获取localStorage
* @method getStorage(name)
* @param {string} name  保存数据的key值,必填
* @example getStorage("aa")
*/
const getStorage = (name) => {
  let item = localStorage.getItem(name);
  if (item) {
    //先尝试进行json字符串转为对象,直接通过localStorage.setItem()存单个字符串的情况
    try {
      item = JSON.parse(item);
    } catch (error) {
      //如果不行就不是json的字符串,就直接返回
      item = item;
    }

    //  判断有没有设置过期时间、保存数据的格式
    //先判断设置时的时间大于0,是否为数字,过期时间是否也为数字
    if ((item['jm_save_startTime'] > 0) && (!isNaN(item['jm_save_startTime'])) && (!isNaN(item['jm_save_time']))) {

      let date = new Date().getTime();    //获取当前时间
      if (item['jm_save_time'] == 0) {   //等于0永不过期
        return item['jm_save_value'];
      } else if (item['jm_save_time'] + item['jm_save_startTime'] > date) {    //开始时间+保存时间如果大于当前时间,(未过期)就返回值,否则清空
        return item['jm_save_value'];
      } else {
        localStorage.removeItem(name);
        return false;
      }

    } else {
      //如果没有设置失效时间,直接返回值
      return item;
    }
  } else {
    return false;
  }
}


/**
* @function 清除localStorage
* @method removeStorage(name)
* @param {string} [name]  保存数据的key值,不填清空所有缓存
* @example removeStorage("aa")
*/
const removeStorage = (name) => {
  if (name) { //有参数清除单条数据
    localStorage.removeItem(name);
  } else {    //无参数清除所有缓存数据
    localStorage.clear();
  }
}


/**
* @function 生成特效文字
* @param {String} [words=''] 需要生成特效的一段文字,默认为空
* @return   返回html标签内容
* @example  effectText('张三')    //<span style="color: #30c26c;font-size: 16px;">张</span><span style="color: #fdb853;font-size: 18px;">三</span>
*/
const effectText = (words = '') => {
  words = [...words]
  let endText = "";
  let arrSize = new Array("12px", "14px", "16px", "18px", "24px", "32px", "48px");    //文字大小
  for (let time = 0; time <= (words.length - 1); time++) {
    if (words[time] != " ") {
      let col = "#" + Math.random().toString(16).slice(-6);  //随机生成hex颜色
      let i = Math.floor((Math.random() * arrSize.length));
      endText += `<span style="color: ${col};font-size: ${arrSize[i]};">${words[time]}</span>`;
    }
  }
  return endText;
}
/**
 * @function 低版本浏览器下,提示用户安装新版浏览器,跳转到下载浏览器页面
 * 
 */
const newBrowser = () => {
  if (navigator.appName == "Microsoft Internet Explorer" && parseInt(navigator.appVersion.split(";")[1].replace(/[ ]/g, "").replace("MSIE", "")) < 9) {
    // https://browsehappy.com/
    window.location.href = "https://support.dmeng.net/upgrade-your-browser.html?referrer=" + location.href;
  }
}

/**
 * @function iframe打开页面不增加浏览器历史记录,(新iframe替换原有iframe,并更换src)
 * @param {String} el iframe标签的类名、属性等等,(例如'#iframe'、'.iframe'、'iframe[name=iframe]')
 * @param {String} url 需要替换的src地址
 */
const openIframe = (el, url) => {
  let oldIframe = document.querySelectorAll(el)[0];
  // oldIframe.contentWindow.location.replace(url);   //方案一可以通过replace来将url替换而不是push到浏览器历史中
  // 方案一,使用新的iframe标签
  if (oldIframe && url) {
    let iframe = oldIframe.cloneNode(true);     //深拷贝旧iframe得到一个新iframe
    iframe.src = url;   //替换src
    oldIframe.parentNode.insertBefore(iframe, oldIframe);//在oldIframe之前添加新的iframe

    //移除旧的iframe
    oldIframe.parentNode.removeChild(oldIframe);
  }
}

/**
* 提示框弹窗
*/
var jmMess = {
  timer: '',  //记录定时器状态
  /**
   * 提示框
   * @method jmMess.msg(value,time,callback)
   * @param {string} value 提示的文字信息
   * @param {string|number} time 弹窗显示的时间,单位ms,(多久关闭弹窗)
   * @param {function} callback 回调函数,弹窗关闭后执行
   * @example 
   * jmMess.msg("文字",5000,function(){})
   */
  msg: function (value, time, callback) {
    // 参数梳理
    if (typeof time === "function") {
      callback = time
    } else if (!isNaN(time)) {
      time = time - 0 >= 0 ? time - 0 : 3000;
    } else {
      time = 3000;
    }
    //清除定时器
    clearTimeout(this.timer);
    //移除提示框
    let old = document.querySelectorAll('[data-jmTips="jmTips"]')[0];
    if (old) {
      document.body.removeChild(old);
    }

    //创建div并设置样式和提示文字内容
    let div = document.createElement('div');
    div.style = 'width: 200px;position: fixed;top: 40%;left:50%;transform: translateX(-50%);text-align: center;z-index:9999;background-color: rgba(0, 0, 0,0.6);font-size: 14px;line-height:1.5;color: #fff;padding: 10px 15px;border-radius: 5px;';
    div.innerHTML = value;
    // div添加属性(标识),追加到DOM
    div.setAttribute("data-jmTips", "jmTips");
    document.body.appendChild(div);

    // 清除提示
    this.timer = setTimeout(function () {
      document.body.removeChild(div);
      if (typeof callback === "function") {
        // 可以组装数据作为回调函数的参数返回使用
        // var mss = { state: 'success' };
        // callback(mss);
        callback();
      }
    }, time);

  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值