JS兼容及常用工具代码封装

本文目录:

  • 1.格式化日期时间函数(formatDate(dt))
  • 2.获取当前浏览器的类型(getBrowserType)
  • 3.获取页面向上或者向左卷曲出去的距离(getPageScroll)
  • 4.限制字符显示字数(cutLongString(string, number))
  • 5.ajax原生代码封装(ajax(url,type,async,timeout,data,success,error))
  • 6.比值函数(compareUp,compareDown,compareObjArr(prop))
  • 7.获取地址栏参数(getUrlParamString(name))
  • 8.移动端适配方案,rem快速布局
  • 9.移动端PC端页面动态跳转解决方案
    1. 取min-max之间的随机数(getRandom(min, max),getRandomPlus(min, max))
  • 11.获取传入参数的数据类型(getParamType(val))
  • 12.深拷贝递归函数(deepCopy(obj))
  • 13.让页面滚动到顶部(scrollToPageTop)
  • 14.判断指定el是否在视口范围内(ifElementIsVisibleInViewport(el))
  • 15.劫持粘贴板(copyTextToClipboard(value))
  • 16.将阿拉伯数字翻译成中文的大写数字(numberToChinese(num))
  • 17.检测密码强度(checkPwd(str))
  • 18.转码和解码(htmlDecodeByRegExp(str),htmlEncodeByRegExp(str))
  • 19.最近n天(getLatestDay)
  • 20.禁止蒙层底部页面跟随滚动(bodyScrollToggle)
  • 21.防抖(debounceFunc(handle, delay))
  • 22.节流(throttleFunc(handler, wait))

1.格式化日期时间函数

参数:只有一个必传参数
默认参数是当前的时间对象
参数支持传入时间对象,或者距 1970 年 1 月 1 日之间的毫秒数
返回值是一个对象{}

function formatDate(dt) {
  if (typeof dt === "object") {
  } else if (typeof dt === "number") {
    dt = new Date(dt);
  } else {
    dt = new Date();
  }
  var str = ""; //存储时间的字符串
  //获取年
  var year = dt.getFullYear();
  //获取月
  var month = dt.getMonth() + 1;
  //获取日
  var day = dt.getDate();
  //获取小时
  var hour = dt.getHours();
  //获取分钟
  var min = dt.getMinutes();
  //获取秒
  var sec = dt.getSeconds();
  month = month < 10 ? "0" + month : month;
  day = day < 10 ? "0" + day : day;
  hour = hour < 10 ? "0" + hour : hour;
  min = min < 10 ? "0" + min : min;
  sec = sec < 10 ? "0" + sec : sec;
  str =
    year + "年" + month + "月" + day + "日 " + hour + ":" + min + ":" + sec;
  return {
    year,
    month,
    day,
    hour,
    min,
    sec,
    str,
  };
}

2.获取当前浏览器的类型

在处理一些兼容性问题的形式可以根据下面的判定进行处理。

function getBrowserType() {
    var broType = ''
    var browserName = navigator.userAgent.toLowerCase()
    if (/msie/i.test(browserName) && !/opera/.test(browserName)) {
        broType = "IE"
    } else if (/firefox/i.test(browserName)) {
        broType = "Firefox"
    } else if (/chrome/i.test(browserName) && /webkit/i.test(browserName) && /mozilla/i.test(browserName)) {
        broType = "Chrome"
    } else if (/opera/i.test(browserName)) {
        broType = "Opera"
    } else if (/webkit/i.test(browserName) && !(/chrome/i.test(browserName) && /webkit/i.test(browserName) && /mozilla/i.test(browserName))) {
        broType = "Safari"
    } else {
        broType = "Unknown"
    }
    return broType
}

3.获取页面向上或者向左卷曲出去的距离

下面封装的函数可以实现最大兼容性的获取到想要的值,返回值是一个对象,top属性对应的向上卷曲出去的距离值,left属性对应的向左卷曲出去的距离值。

function getPageScroll() {
    return {
        top: window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop || 0,
        left: window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft || 0
    }
}

4.限制字符显示字数

方法需要传两个参数,第一个参数是需要传入的字符串,第二个参数是需要保留的字符串字数

function cutLongString(string, number) {
    let newString = ''
    if (string.length > number) {
        return newString = string.substring(0, number) + '...'
    } else {
        return newString
    }
}

5.ajax原生代码封装

调用时的参数

ajax({
    url: "", //请求地址
    type: 'GET', //请求方式
    async: true,//同步异步设置
    timeout: 6000,//超时设置
    data: {
        name: '',
        age: '',
        email: ''
    }, //请求参数
    success: function(response, xml) {
        console.log(response); //   此处执行请求成功后的回调
    },
    error: function(status) {
        console.log('状态码为' + status); // 此处为请求失败后的回调
    }
})

代码封装

const ajax = function (options) {
    options = options || {};
    options.type = (options.type || "GET").toUpperCase();
    options.dataType = options.dataType || 'json';
    options.async = options.async || true;
    options.timeout = options.timeout || 5000;//超时处理,默认5s
    var params = getParams(options.data);
    var timeoutFlag = null;
    var xhr;
    var that = this;
    if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest();
    } else {
        xhr = new ActiveXObject('Microsoft.XMLHTTP')
    }
    xhr.onreadystatechange = function () {
        if (options.dataType === 'json') {
            if (xhr.readyState == 4) {
                window.clearTimeout(that.timeoutFlag);
                var status = xhr.status;
                if (status >= 200 && status < 300) {
                    // 如果需要像 html 表单那样 POST 数据,请使用 setRequestHeader() 来添加 http 头。
                    options.success && options.success(xhr.responseText, xhr.responseXML);
                } else {
                    options.error && options.error(status);
                }
            }
        } else {
            if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
                window.clearTimeout(that.timeoutFlag);
                var oScript = document.createElement('script');
                document.body.appendChild(oScript);
                var callbackname = 'ajaxCallBack'
                oScript.src = options.url + "?" + params + '&callback=' + callbackname;
                window['ajaxCallBack'] = function (data) {
                    options.success(data);
                    document.body.removeChild(oScript);
                };
            }
        }
    };
    if (options.type == 'GET') {
        xhr.open("GET", options.url + '?' + params, options.async);
        xhr.send(null)
    } else if (options.type == 'POST') {
        xhr.open('POST', options.url, options.async);
        if (options.contentType == "undefined" || options.contentType == null) {
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.send(params);
        } else {
            xhr.setRequestHeader('Content-Type', options.contentType);
            xhr.send(JSON.stringify(options.data));
        }
    }
    this.timeoutFlag = window.setTimeout(function () {//计时器,超时后处理
        window.clearTimeout(that.timeoutFlag);
        //options.error("timeout");
        xhr.abort();
    }.bind(this), options.timeout);
}
function getParams(data) {
    var arr = [];
    for (var param in data) {
        arr.push(encodeURIComponent(param) + '=' + encodeURIComponent(data[param]));
    }
    return arr.join('&');
}

6.比值函数

普通比值函数:直接把变量放入sort方法中即可

const compareUp = function (a, b) {//升序比值函数
    if (a < b) {
        return -1;
    } else if (a > b) {
        return 1;
    } else {
        return 0;
    }
}
const compareDown = function (a, b) {//降序比值函数
    if (a < b) {
        return 1;
    } else if (a > b) {
        return -1;
    } else {
        return 0;
    }
}

排序对象数组的比值函数:参数传入要进行排序的属性名

const compareObjArr = function (prop) {
    return function (obj1, obj2) {
        var val1 = obj1[prop];
        var val2 = obj2[prop];
        if (!isNaN(Number(val1)) && !isNaN(Number(val2))) {
            val1 = Number(val1);
            val2 = Number(val2);
        }
        if (val1 < val2) {
            return -1;
        } else if (val1 > val2) {
            return 1;
        } else {
            return 0;
        }
    }
}

7.获取地址栏参数

参数传入什么,返回的就是地址栏上对应的参数值

const getUrlParamString = function (name) {
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); // 构造一个含有目标参数的正则表达式对象
    var r = window.location.search.substr(1).match(reg);  // 匹配目标参数
    if (r != null) return unescape(r[2]); return null; // 返回参数值
}

8.移动端适配方案,rem快速布局

PC端使用请将此代码注释掉
750px图,图片尺寸/100=rem尺寸
iphone调试开发,屏幕尺寸/100*2=rem尺寸

(function () {
    var width = document.documentElement.clientWidth;
    var html = document.querySelector("html");
    html.style.fontSize = width / 7.5 + "px";
})();

9.移动端PC端页面动态跳转解决方案

将此JS代码放到跳板页面的头部

function IsPC() {
    var userAgentInfo = navigator.userAgent;
    var Agents = ["Android", "iPhone",
        "SymbianOS", "Windows Phone",
        "iPad", "iPod"];
    var flag = true;
    for (var v = 0; v < Agents.length; v++) {
        if (userAgentInfo.indexOf(Agents[v]) > 0) {
            flag = false;
            break;
        }
    }
    return flag;
}
IsPC();
if (!IsPC()) {
    //跳到移动端
    window.location.href = '';
} else {
    //跳到PC端
    window.location.href = '';
}

10. 取min-max之间的随机数

函数始终返回介于 min(包括)和 max(不包括)之间的随机数
函数始终返回介于 min(包括)和 max(不包括)之间的随机整数

const getRandom = function (min, max) {
    return Math.floor(Math.random() * (max - min) ) + min;
}

这个 JavaScript 函数始终返回介于 min 和 max(都包括)之间的随机整数:

const getRandomPlus = function (min, max) {
    return Math.floor(Math.random() * (max - min + 1) ) + min;
}

11.获取传入参数的数据类型

const getParamType = function (val) {
    var s = Object.prototype.toString.call(val)
    var shorts = s.slice(8)
    return shorts.replace(shorts.slice(-1), '').toLowerCase()
}

12.深拷贝递归函数

根据传递进来的参数,返回值是一个深拷贝出来的新数据

const deepCopy = function (obj) {
    var newobj = obj.constructor === Array ? [] : {};
    if (typeof obj !== 'object') {
        return;
    }
    for (var i in obj) {
        newobj[i] = typeof obj[i] === 'object' ?
        deepCopy(obj[i]) : obj[i];
    }
    return newobj
}

13.让页面滚动到顶部

const scrollToPageTop = () => {
    const c = document.documentElement.scrollTop || document.body.scrollTop;
    if (c > 0) {
        window.requestAnimationFrame(scrollToTop);
        window.scrollTo(0, c - c / 8);
    }
}

14.判断指定el是否在视口范围内

需要指定的el全部都在视口范围内才会返回true,只要有任何一部分不在视口范围都会返回false

const ifElementIsVisibleInViewport = (el, partiallyVisible = false) => {
    const {
        top,
        left,
        bottom,
        right
    } = el.getBoundingClientRect();
    const {
        innerHeight,
        innerWidth
    } = window;
    return partiallyVisible ?
        ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
        ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth)) :
        top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
}

15.劫持粘贴板

比如想要将类名为demo的文本内容复制到粘贴板,先获取到内容let demo = document.querySelector(".demo"),然后调用工具函数copyTextToClipboard(demo.innerText)

const copyTextToClipboard = (value) => {
    var textArea = document.createElement("textarea");
    textArea.style.background = 'transparent';
    textArea.value = value;
    document.body.appendChild(textArea);
    textArea.select();
    try {
        var successful = document.execCommand('copy');
    } catch (err) {
        console.log('Oops, unable to copy');
    }
    document.body.removeChild(textArea);
}

16.将阿拉伯数字翻译成中文的大写数字

const numberToChinese = (num) => {
    var AA = new Array("零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十");
    var BB = new Array("", "十", "百", "仟", "萬", "億", "点", "");
    var a = ("" + num).replace(/(^0*)/g, "").split("."),
        k = 0,
        re = "";
    for (var i = a[0].length - 1; i >= 0; i--) {
        switch (k) {
            case 0:
                re = BB[7] + re;
                break;
            case 4:
                if (!new RegExp("0{4}//d{" + (a[0].length - i - 1) + "}$")
                    .test(a[0]))
                    re = BB[4] + re;
                break;
            case 8:
                re = BB[5] + re;
                BB[7] = BB[5];
                k = 0;
                break;
        }
        if (k % 4 == 2 && a[0].charAt(i + 2) != 0 && a[0].charAt(i + 1) == 0)
            re = AA[0] + re;
        if (a[0].charAt(i) != 0)
            re = AA[a[0].charAt(i)] + BB[k % 4] + re;
        k++;
    }
    if (a.length > 1) // 加上小数部分(如果有小数部分)
    {
        re += BB[6];
        for (var i = 0; i < a[1].length; i++)
            re += AA[a[1].charAt(i)];
    }
    if (re == '一十')
        re = "十";
    if (re.match(/^一/) && re.length == 3)
        re = re.replace("一", "");
    return re;
}

17.检测密码强度

当返回值为0时,提示密码长度不得少于6位数
数字,小写字母,大写字母,.-_三种特殊符号,每多一种,安全级别加1,最高级别4

const checkPwd = (str) => {
    let Lv = 0;
    if (str.length < 6) {
        return Lv
    }
    if (/[0-9]/.test(str)) {
        Lv++
    }
    if (/[a-z]/.test(str)) {
        Lv++
    }
    if (/[A-Z]/.test(str)) {
        Lv++
    }
    if (/[\.|-|_]/.test(str)) {
        Lv++
    }
    return Lv;
}

18.转码和解码

const htmlDecodeByRegExp = function (str) {
    var s = "";
    if (str.length == 0) return "";
    s = str.replace(/&amp;/g, "&");
    s = s.replace(/&lt;/g, "<");
    s = s.replace(/&gt;/g, ">");
    s = s.replace(/&nbsp;/g, " ");
    s = s.replace(/&#39;/g, "'");
    s = s.replace(/&quot;/g, '"');
    return s;
}
const htmlEncodeByRegExp = function (str) {
    var s = "";
    if (str.length == 0) return "";
    s = str.replace(/&/g, "&amp;");
    s = s.replace(/</g, "&lt;");
    s = s.replace(/>/g, "&gt;");
    s = s.replace(/ /g, "&nbsp;");
    s = s.replace(/\'/g, "&#39;");
    s = s.replace(/\"/g, "&quot;");
    return s;
}

19.最近n天

两个参数,第1个参数是数字类型,代表想要的是最近几天
第二个参数是字符串类型,asc代表升序,desc代表降序
两个参数都是选填,不传的话默认是返回最近7天的升序

const getLatestDay = function (n=7, sort) {
    sort = sort || 'asc'
    if (sort === 'asc') {
        return [...new Array(n)].map((j, i) => new Date(Date.now() - i * 8.64e7).toLocaleDateString()).reverse()
    } else if (sort === 'desc') {
        return [...new Array(n)].map((j, i) => new Date(Date.now() - i * 8.64e7).toLocaleDateString())
    }
}

20.禁止蒙层底部页面跟随滚动

既然我们要阻止页面滚动,那么何不将其固定在视窗(即position: fixed),这样它就无法滚动了,当蒙层关闭时再释放。
当然还有一些细节要考虑,将页面固定视窗后,内容会回头最顶端,这里我们需要记录一下,同步top值。

let topPosition = 0

const bodyScrollToggle = function (isFixed) {
let bodyEl = document.body
  if (isFixed) {
    topPosition = window.scrollY
    bodyEl.style.position = 'fixed'
    bodyEl.style.top = -topPosition + 'px'
  } else {
    bodyEl.style.position = ''
    bodyEl.style.top = ''
    window.scrollTo(0, topPosition) // 回到原先的top
  }
}

21.防抖

const debounceFunc = function (handle, delay) {
    var timer = null;
    return function () {
        var _self = this,
            _args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function () {
            handle.apply(_self, _args)
        }, delay)
    }
}

22.节流

const throttleFunc = function (handler, wait) {
    var lastTime = 0;
    return function (e) {
        var nowTime = new Date().getTime();
        if (nowTime - lastTime > wait) {
            handler.apply(this, arguments);
            lastTime = nowTime;
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容