工具封装

对象深拷贝

  1. //ES5写法
  2. //循环对象之前需要检测对象里面的属性值是否是引用值
  3. //当发现有引用值的时候需要遍历
  4. //不仅判断键值对是否含有引用值,还得判断是对象还是数组
  5. //利用递归克隆函数进行再次循环
  6. function deepClone(origin, target) {
  7. //万一用户不传target参数,自己默认创建空对象
  8. var target = target || {},
  9. toStr = Object.prototype.toString,
  10. arrType = '[object Array]';
  11. for (var key in origin) {
  12. //排除原型上的属性
  13. if (origin.hasOwnProperty(key)) {
  14. //判断是否为引用值 同时排除null
  15. if (typeof (origin[key]) === 'object' && origin[key] !== null) {
  16. //判断引用值是否为数组类型
  17. if (toStr.call(origin[key]) === arrType) {
  18. //创建空数组
  19. target[key] = [];
  20. } else {
  21. //引用值是对象
  22. //创建空对象
  23. target[key] = {};
  24. }
  25. //递归,再次遍历
  26. deepClone(origin[key], target[key]);
  27. } else {
  28. //这里是递归的出口
  29. //遍历第一层 浅拷贝
  30. target[key] = origin[key];
  31. }
  32. }
  33. }
  34. return target;
  35. }
  36. // // var person2 = deepClone(person1);
  1. //ES6 - weekmap写法
  2. //ES6 WeekMap实现对象深克隆
  3. //Map 键名为任意类型
  4. //WeekMap 键名只能为对象
  5. //本质区别
  6. //WeekMap为弱引用,会被垃圾回收,存在意义是希望键名的对象被回收时,键值也被回收掉
  7. //而函数移除需要赋值为null才能被垃圾回收
  8. //原理: 对象被拷贝过的,再拷贝就会死循环,利用weekmap记录一下是否被拷贝过
  9. var oldObj = {
  10. a: 1,
  11. b: 2,
  12. c: {
  13. e: 3,
  14. f: 4
  15. },
  16. d: ['5', '6', '7']
  17. }
  18. /**
  19. * 深拷贝对象
  20. * @param {*} origin 旧的数据
  21. * @hashMap 记录过的weakmap类型数据,唯一hash值,弱引用值是键名
  22. */
  23. function deepClone(origin, hashMap = new WeakMap()) {
  24. //排除null undefined
  25. //排除原始值
  26. //null == undefined => true
  27. //null === undefined => false
  28. if (origin == undefined || typeof origin !== 'object') {
  29. //不做处理返回对象本身
  30. return origin;
  31. }
  32. //Date RegExp
  33. if (origin instanceof Date) {
  34. return new Date(origin);
  35. }
  36. if (origin instanceof RegExp) {
  37. return new RegExp(origin);
  38. }
  39. //找到对象键名里面值
  40. const hashKey = hashMap.get(origin);
  41. //判断是否存在
  42. if (hashKey) {
  43. //返回本身不做处理
  44. return hashKey;
  45. }
  46. //通过对象的构造器new一个新的实例对象
  47. //此方式数组也适用
  48. const target = new origin.constructor();
  49. //记录保存一下是否有过深拷贝
  50. //如果之前拷贝过了就不会再次拷贝
  51. hashMap.set(origin, target);
  52. //{} []
  53. for (let k in origin) {
  54. //如果对象里包含本身的属性则拷贝
  55. if (origin.hasOwnProperty(k)) {
  56. //将原来的对象复制到新的对象
  57. //如果原来对象里面的属性也有对象,则递归复制
  58. target[k] = deepClone(origin[k], hashMap);
  59. }
  60. }
  61. return target;
  62. }
  63. console.log(oldObj);
  64. //{a: 1, b: 2, c: {e: 3, f: 4}, d: ["5", "6", "7"]}
  65. const newObj = deepClone(oldObj);
  66. newObj.c.g = 5;
  67. newObj.d[3] = '8';
  68. console.log(newObj);
  69. //{a: 1, b: 2, c: {e: 3, f: 4, g: 5}, d: ["5", "6", "7", "8"]}

类型查找

  1. //封装myTypeof()
  2. function myTypeof(val) {
  3. var type = typeof (val),
  4. toStr = Object.prototype.toString,
  5. res = {
  6. '[object Array]': 'array',
  7. '[object Object]': 'object',
  8. '[object Number]': 'object number',
  9. '[object String]': 'object string',
  10. '[object Boolean]': 'object boolean'
  11. }
  12. if (val === null){
  13. return 'null';
  14. //object: null {} []
  15. //这里返回包括包装类Number, String, Boolean
  16. } else if (type === 'object') {
  17. var ret = toStr.call(val);
  18. return res[ret];
  19. //返回原始值
  20. //
  21. } else {
  22. return type;
  23. }
  24. }

滚动距离

  1. /**
  2. * 封装兼容IE8&IE9以下的滚动条距离函数
  3. * @返回值 返回左/上滚动距离
  4. * 找到滚动距离
  5. * getScrollOffset()
  6. */
  7. function getScrollOffset() {
  8. if (window.pageXOffset) {
  9. return {
  10. left: window.pageXOffset,
  11. top: window.pageYOffset
  12. }
  13. } else {
  14. return {
  15. left: document.body.scrollLeft + document.documentElement.scrollLeft,
  16. top: document.body.scrollTop + document.documentElement.scrollTop
  17. }
  18. }
  19. }
  20. getScrollOffset().top;

可视区域

  1. /**
  2. * 封装兼容IE8&IE9以下的可视区域宽高尺寸的函数
  3. * 获取可视窗口宽度/高度
  4. * 原理:判断模式是否为怪异
  5. */
  6. function getViewportSize() {
  7. if (window.innerWidth) {
  8. return {
  9. width: window.innerWidth,
  10. height: window.innerHeight
  11. }
  12. } else {
  13. if (document.compatMode === 'BackCompat') {
  14. return {
  15. width: document.body.clientWidth,
  16. height: document.body.clientHeight
  17. }
  18. } else {
  19. return {
  20. width: document.documentElement.clientWidth,
  21. height: document.documentElement.clientHeight
  22. }
  23. }
  24. }
  25. }
  26. getViewportSize().width

滚动长度

  1. /**
  2. * 封装兼容IE8&IE9以下的滚动尺寸的函数
  3. * 获取整个文档的宽度/高度
  4. */
  5. function getScrollSize() {
  6. if (document.body.scrollWidth) {
  7. return {
  8. width: document.body.scrollWidth,
  9. height: document.body.scrollHeight
  10. }
  11. } else {
  12. return {
  13. width: document.documentElement.scrollWidth,
  14. height: document.documentElement.scrollHeight
  15. }
  16. }
  17. }
  18. getScrollSize().width

查看盒子到页面边缘的距离

  1. /**
  2. * 封装合并子盒子与父盒子到左侧/上侧 到 页面左侧/上侧的 距离
  3. */
  4. function getElemDocPosition(el) {
  5. //找到有定位的父级盒子
  6. var parent = el.offsetParent,
  7. //找到当前盒子左侧/上侧到页面左侧/上侧的距离
  8. offsetLeft = el.offsetLeft,
  9. offsetTop = el.offsetTop;
  10. // 如果parent存在
  11. while (parent) {
  12. // 循环出来的parent是定位元素
  13. offsetLeft += parent.offsetLeft;
  14. offsetTop += parent.offsetTop;
  15. //重新赋值parent,找到外层盒子继续加
  16. parent = parent.offsetParent;
  17. }
  18. return {
  19. left: offsetLeft,
  20. top: offsetTop
  21. }
  22. }
  23. getElemDocPosition(son);
  24. //{left: 230, top: 230}

鼠标坐标

  1. /**
  2. * 封装页面坐标函数pagePos()
  3. * @e 元素
  4. * @返回值 页面内的x/y坐标
  5. */
  6. function pagePos(e) {
  7. //获取滚动条距离
  8. //使用获取滚动条距离函数
  9. var sLeft = getScrollOffset().left,
  10. sTop = getScrollOffset().top,
  11. //获取文档偏移
  12. //documentElement.clientLeft IE8及以下不存在(undefined)
  13. cLeft = document.documentElement.clientLeft || 0,
  14. cTop = document.documentElement.clientTop || 0;
  15. return {
  16. //可视区域坐标 + 滚动条距离 - 偏移距离
  17. X: e.clientX + sLeft - cLeft,
  18. Y: e.clientY + sTop - cTop
  19. }
  20. }

鼠标拖拽

  1. /**
  2. * 封装拖拽函数
  3. */
  4. function elemDrag(elem) {
  5. var x, y;
  6. //鼠标按下时
  7. addEventListener(elem, "mousedown", function (e) {
  8. var e = e || window.event;
  9. //pagePos()找到鼠标点击的坐标
  10. //getStyles()找到目标元素左上顶点到浏览器窗口边缘的left/top值
  11. x = pagePos(e).X - getStyles(elem, "left");
  12. y = pagePos(e).Y - getStyles(elem, "top");
  13. addEventListener(document, "mouseMove", mousemove);
  14. addEventListener(document, "mouseUp", mouseup);
  15. cancelBubble(e);
  16. preventDefaultEvent(e);
  17. });
  18. //鼠标移动时
  19. function mouseMove(e) {
  20. var e = e || window.event;
  21. //鼠標移動后有新的pagePos().X/Y值
  22. //雖然鼠標位置變了,但是計算后的x/y值是不變的
  23. //新的pagePos().X/Y值 - x/y = 新目標元素到瀏覽器邊緣的距離
  24. elem.style.top = pagePos(e).Y - y + "px";
  25. elem.style.left = pagePos(e).X - x + "px";
  26. }
  27. //鼠标抬起时释放绑定的事件
  28. function mouseUp(e) {
  29. var e = e || window.event;
  30. removeEvent(document, "mousemove", mouseMove);
  31. removeEvent(document, "mouseup", mouseUp);
  32. }
  33. }

元素属性

  1. /**
  2. * 获取元素属性
  3. * @elem 元素
  4. * @prop 属性
  5. * @返回值 返回指定元素的属性值
  6. */
  7. function getStyles(elem, prop) {
  8. //检测getComputedStyle是否存在
  9. if (window.getComputedStyle) {
  10. //存在,打印具体属性值
  11. if (prop) {
  12. return parseInt(window.getComputedStyle(elem, null)[prop]);
  13. }
  14. //不存在,打印集合
  15. return window.getComputedStyle(elem, null);
  16. } else {
  17. if (prop) {
  18. return parseInt(elem.currentStyle[prop]);
  19. } else {
  20. return elem.currentStyle;
  21. }
  22. }
  23. }
  24. getStyles(div);
  25. getStyles(div, 'height'); //200px

事件函数

  1. /**
  2. * 封装兼容低版本的事件绑定处理函数
  3. * @el 元素
  4. * @type 事件类型
  5. * @fn 事件处理函数
  6. */
  7. function addEvent(el, type, fn) {
  8. if (el.addEventListener) {
  9. el.addEventListener(type, fn, false);
  10. } else if (el.attachEvent) {
  11. el.attachEvent('on' + type, function () {
  12. fn.call(el);
  13. })
  14. } else {
  15. el['on' + type] = fn;
  16. }
  17. }

移除事件

  1. /**
  2. * 解除事件处理函数
  3. * @el 元素
  4. * @type 事件类型
  5. * @fn 事件处理函数
  6. */
  7. function removeEvent(elem, type, fn) {
  8. if (elem.addEventListener) {
  9. elem.removeEventListener(type, fn, false);
  10. } else if (elem.attachEvent) {
  11. elem.detachEvent('on' + type, fn);
  12. } else {
  13. elem['on' + 'type'] = null;
  14. }
  15. }

找子元素

  1. //找子元素函数
  2. function elemChildren(node) {
  3. var temp = {
  4. 'length': 0,
  5. 'push': Array.prototype.push,
  6. 'splice': Array.prototype.splice
  7. };
  8. var children = node.childNodes,
  9. len = children.length,
  10. item;
  11. for (var i = 0; i < len; i++) {
  12. item = children[i];
  13. if (item.nodeType === 1) {
  14. temp.push(item);
  15. }
  16. }
  17. return temp;
  18. }

找父元素

  1. /**
  2. * 封装找父级元素的函数
  3. * @node 子元素节点
  4. * @n 寻找第几个父级元素
  5. * @返回值 返回父级元素
  6. */
  7. function elemParent(node, n) {
  8. var type = typeof (n);
  9. if (type === 'undefined') {
  10. return node.parentNode;
  11. } else if (n <= 0 || type !== 'number') {
  12. return undefined;
  13. }
  14. while (n) {
  15. node = node.parentNode;
  16. n--;
  17. }
  18. return node;
  19. }

取消冒泡

  1. /**
  2. * 兼容性写法封装:
  3. * 封装取消冒泡方法
  4. */
  5. function cancelBubble(e) {
  6. var e = e || window.event;
  7. if (e.stopPropagation) {
  8. e.stopPropagation();
  9. } else {
  10. e.cancelBubble = true;
  11. }
  12. }
  1. /**
  2. * 兼容性写法封装:
  3. * 封装取消冒泡方法
  4. */
  5. function preventDefaultEvent(e) {
  6. var e = e || window.event;
  7. if (e.preventDefault) {
  8. event.preventDefault();
  9. } else {
  10. event.returnValue = false;
  11. }
  12. }

文档解析

封装文档解析完毕函数

  1. function domReady(fn) {
  2. if (document.addEventListener) {
  3. document.addEventListener('DOMContentLoaded', function () {
  4. //释放内容
  5. document.removeEventListener('DOMContentLoaded', arguments.callee, false);
  6. fn();
  7. }, false);
  8. //兼容IE
  9. } else if (document.attachEvent) {
  10. document.attachEvent('onreadystatechange', function () {
  11. //文档加载完成
  12. if (this.readyState === 'complete') {
  13. document.attachEvent('onreadystatechange', arguments.callee);
  14. fn();
  15. }
  16. })
  17. }
  18. //doScroll可以操作滚动条
  19. //如果文档没有解析完渲染完会报错
  20. if (document.documentElement.doScroll && typeof (window.frameElement) === 'undefined') {
  21. try {
  22. document.documentElement.doScroll('left');
  23. } catch (e) {
  24. return setTimeout(arguments.callee, 20);
  25. }
  26. fn();
  27. }
  28. }
  29. domReady(fn);

行为预测

判断是否在三角区域

  1. /**
  2. * 行为预测技术:
  3. * 判断是否在三角区域
  4. */
  5. //判断点是否在一个三角形内
  6. function vec(a, b) {
  7. return {
  8. x: b.x - a.x,
  9. y: b.y - a.y
  10. }
  11. }
  12. function vecProduct(v1, v2) {
  13. return v1.x * v2.y - v2.x * v1.y;
  14. }
  15. function sameSymbols(a, b) {
  16. return (a ^ b) >= 0;
  17. }
  18. function pointInTriangle(p, a, b, c) {
  19. var PA = vec(p, a),
  20. PB = vec(p, b),
  21. PC = vec(p, c),
  22. R1 = vecProduct(PA, PB),
  23. R2 = vecProduct(PB, PC),
  24. R3 = vecProduct(PC, PA);
  25. return sameSymbols(R1, R2) && sameSymbols(R2, R3);
  26. }

模板替换

  1. // 正则规则
  2. function regTpl() {
  3. // gim 全局大小写不敏感多行
  4. return new RegExp(/{{(.*?)}}/, 'gim');
  5. }
  6. /**
  7. * 字符串替换
  8. * @tpl 模板
  9. * @regExp 匹配规则
  10. * @opt 一个对象保存被传的key值
  11. *
  12. * 函数是匹配规则:关键点根据正则匹配{{}}里的某一个key值
  13. * @node 关键点 如 {{career}}
  14. * @key 就是opt对象里面的属性值
  15. */
  16. function setTplToHTML(tpl, regExp, opt) {
  17. // ''.replace(替换目标, 替换值)
  18. // ''.replace(正则表达式, 函数(node,key){})
  19. return tpl.replace(regExp(), function (node, key) {
  20. //return被替换的key值
  21. return opt[key];
  22. });
  23. }
  24. //调用写法:
  25. list += setTplToHTML(tpl, regTpl, {
  26. career: item.career,
  27. city: item.city,
  28. salary: item.salary,
  29. img: item.img
  30. });

AJAX

  1. /**
  2. * AJAX封装
  3. *
  4. * 调用写法一:
  5. * $.ajax({
  6. * url: 'xxx',
  7. * type: 'POST',
  8. * dataType: 'JSON',
  9. * data: {
  10. * status: 1
  11. * },
  12. * success: function (data) {
  13. * console.log(data);
  14. * }
  15. * })
  16. *
  17. * 调用写法二:
  18. * $.post('http://localhost/xxx', { status: 1 }, function (data) { console.log(data); });
  19. *
  20. * 调用写法三:
  21. * $.get('http://localhost/xxx?status=1', function (data) { console.log(data); });
  22. *
  23. *
  24. */
  25. //老写法:
  26. // var $ = {
  27. // ajax: function (opt) {
  28. // var url = opt.url;
  29. // console.log(url);
  30. // },
  31. // post: function () {
  32. // console.log('post');
  33. // },
  34. // get: function () {
  35. // console.log('get');
  36. // }
  37. // }
  38. // 模块化写法
  39. var $ = (function () {
  40. //利用_doAjax函数传参拿到局部作用域ajax函数里的形参
  41. function _doAjax(opt) {
  42. //兼容IE5,IE6
  43. var o = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
  44. //IE4及以下
  45. if (!o) {
  46. throw new Error('您的浏览器不支持异步发起HTTP请求');
  47. }
  48. //初始化传入的配置
  49. var opt = opt || {},
  50. // console.log(opt); //{type: "POST"}
  51. //初始化请求类型为GET
  52. type = (opt.type || 'GET').toUpperCase(),
  53. // console.log(type); //POST
  54. // 同步/异步 false/true
  55. async = '' + opt.async === 'false' ? false : true,
  56. url = opt.url,
  57. //如果GET请求就为null
  58. data = opt.data || null,
  59. //响应数据
  60. dataType = opt.dataType || 'JSON',
  61. //后端定义的cb或callback字符串
  62. jsonp = opt.jsonp || 'cb',
  63. //定义的函数名称方便给后端匹配
  64. jsonpCallback = opt.jsonpCallback || 'jQuery' + randomNum() + '_' + new Date().getTime(),
  65. timeout = opt.timeout || 30000,
  66. error = opt.error || function () {},
  67. success = opt.success || function () {},
  68. //不管成功或失败都执行complete函数
  69. complete = opt.complete || function () {},
  70. // 初始化定时器
  71. t = null;
  72. if (!url) {
  73. throw new Error('您没有填写url');
  74. }
  75. if (dataType.toUpperCase === 'JSONP' && type !== 'GET') {
  76. throw new Error('如果dataType为JSONP,请您将type设置为GET');
  77. }
  78. //格式: xxx.domain.com/xxx.php?jsonp=jsonpCallback
  79. //情况1:xxx.domain.com/xxx.php?cb=test
  80. //情况2:xxx.domain.com/xxx.php?wd=xxx&cb=test
  81. if (dataType.toUpperCase() === 'JSONP') {
  82. var oScript = document.createElement('script');
  83. oScript.src = url.indexOF('?') === -1 ?
  84. //情况1:如果没有? 则加?
  85. url + '?' + jsonp + '=' + jsonpCallback :
  86. //情况2:如果有? 证明多参数情况下加 & 隔开
  87. url + '&' + jsonp + '=' + jsonpCallback;
  88. document.body.appendChild(oScript);
  89. document.body.removeChild(oScript);
  90. //定义函数并挂载到window
  91. window[jsonpCallback] = function (data) {
  92. //关联ajax里的success函数,执行success函数
  93. success(data);
  94. }
  95. //阻止ajax向下执行
  96. return;
  97. }
  98. /**发送HTTP请求
  99. * @type 请求类型
  100. * @url 请求地址
  101. * @async 异步/同步
  102. */
  103. o.open(type, url, async);
  104. //超时设置 写法一: 设置超时时间 30s
  105. //兼容性不太好
  106. // o.ontimeout = 30000;
  107. //设置POST请求头
  108. //如果为真走后面
  109. type === 'POST' && o.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  110. //如果是GET请求,不用传参数
  111. o.send(type === 'GET' ? null : formatDatas(data));
  112. //监听响应事件
  113. o.onreadystatechange = function () {
  114. if (o.readyState === 4) {
  115. //请求已完成,且响应已就绪
  116. if (o.status >= 200 && o.status < 300 && o.status === 304) {
  117. switch (dataType.toUpperCase()) {
  118. case 'JSON':
  119. // 成功时响应服务器JSON数据
  120. success(JSON.parse(o.responseText));
  121. break;
  122. case 'TEXT':
  123. // 成功时响应服务器文本数据
  124. success(o.responseText);
  125. break;
  126. case 'XML':
  127. // 成功时响应服务器XML数据
  128. success(o.responseXML);
  129. break;
  130. default:
  131. // 默认响应服务器JSON数据
  132. success(JSON.parse(o.responseText));
  133. }
  134. } else {
  135. error();
  136. }
  137. // 无论成功与否都要执行complete函数
  138. complete();
  139. clearTimeout(t);
  140. t = null;
  141. o = null;
  142. }
  143. }
  144. // 超时设置 写法一:
  145. //只要超时就会执行的函数
  146. //兼容性不太好
  147. // o.ontimeout = function () {
  148. // //o对象的所有程序都会中止
  149. // o.abort();
  150. // //并销毁对象
  151. // o = null;
  152. // }
  153. // 超时设置 写法二:
  154. t = setTimeout(function () {
  155. //o对象的所有程序都会中止
  156. o.abort();
  157. clearTimeout(t);
  158. t = null;
  159. o = null;
  160. //抛出错误
  161. throw new Error('This request has been timeout for' + url);
  162. }, timeout);
  163. }
  164. //希望将{status:1,flag:2}转为'status=1&flag=2'
  165. //格式化传入的data数据
  166. function formatDatas(obj) {
  167. var str = '';
  168. for (var key in obj) {
  169. str += key + '=' + obj[key] + '&';
  170. }
  171. //去掉最后一项的 &
  172. //正则规则:以&结尾 替换为空字符
  173. return str.replace(/&$/, '');
  174. }
  175. return {
  176. ajax: function (opt) {
  177. _doAjax(opt);
  178. },
  179. get: function (url, dataType, successCB, errorCB, completeCB) {
  180. _doAjax({
  181. type: 'GET',
  182. url: url,
  183. dataType: dataType,
  184. success: successCB,
  185. error: errorCB,
  186. complete: completeCB
  187. });
  188. },
  189. post: function (url, data, dataType, successCB, errorCB, completeCB) {
  190. _doAjax({
  191. type: 'POST',
  192. url: url,
  193. data: data,
  194. dataType: dataType,
  195. success: successCB,
  196. error: errorCB,
  197. complete: completeCB
  198. });
  199. }
  200. }
  201. })();
  202. //随机生成
  203. function randomNum() {
  204. var num = '';
  205. for (var i = 0; i < 20; i++) {
  206. num += Math.floor(Math.random() * 10);
  207. }
  208. return num;
  209. }

替换空格

  1. function trimSpace(str) {
  2. return str.replace(/\s+/gim, '');
  3. }

事件源

  1. /**
  2. * 封装 获取target 函数 并兼容IE
  3. * @param {*} e 事件对象
  4. * @param {*} mark 标识 判断是tagName 还是 className
  5. * @返回值 一个对象包含tar和mark
  6. */
  7. function getTarget(e, mark) {
  8. var e = e || window.event,
  9. tar = e.target || e.srcElement;
  10. mark = mark == 'className' ? tar.className : tar.tagName.toLowerCase();
  11. return {
  12. tar: tar,
  13. mark: mark
  14. }
  15. }

获取节点

  1. /**
  2. * 封装获取元素节点函数(类似jquery)
  3. * 执行语句写法:
  4. * $get('.box')[0]
  5. * $get('#box')
  6. * $get('div')[2]
  7. */
  8. function $get(target) {
  9. //找到第一个字符
  10. var _s = target.charAt(0),
  11. rTarget = target.replace(_s, '');
  12. switch (_s) {
  13. case '#':
  14. //id
  15. return document.getElementById(rTarget);
  16. break;
  17. case '.':
  18. //class
  19. return document.getElementsByClassName(rTarget);
  20. break;
  21. default:
  22. return document.getElementsByTagName(target);
  23. }
  24. }

异步加载

写法一

  1. //阻塞onload执行
  2. //异步加载
  3. (function () {
  4. //阻塞onload执行
  5. function async_load() {
  6. var s = document.createElement("script");
  7. s.type = "text/javascript";
  8. s.async = true;
  9. s.src = "utils.js";
  10. oScript.parentNode.insertBefore(s, oScript);
  11. //执行
  12. document.body.appendChild(s);
  13. }
  14. if (window.attachEvent) {
  15. window.attachEvent("onload", async_load);
  16. } else {
  17. window.addEventListener("load", async_load, false);
  18. }
  19. })();

写法二

  1. // 通过readyState事件判断 -> onreadystatechange输出的值判断页面是否加载完毕 -> IE
  2. function exec_util_with_loading_script(url, fn) {
  3. //异步加载
  4. var s = document.createElement('script'),
  5. oScript = document.getElementsByTagName('script')[0];
  6. s.type = 'text/javascript';
  7. //如果存在,则为IE浏览器
  8. //readyState为标签返回的状态码
  9. if (s.readyState) {
  10. s.onreadychange = function () {
  11. var state = s.readyState;
  12. //onload会一直监听页面加载是否完毕
  13. if (state === 'complete' || state === 'loaded') {
  14. utils[fn]();
  15. }
  16. }
  17. } else {
  18. s.onload = function () {
  19. utils[fn]();
  20. }
  21. }
  22. //readyState需要在资源加载完毕后才执行
  23. s.src = url;
  24. oScript.parentNode.insertBefore(s, oScript);
  25. }
  26. //调用
  27. exec_util_with_loading_script('utils.js', 'test')

时间日期

  1. /**
  2. * 格式化时间日期
  3. * JavaScript时间单位带毫秒
  4. * PHP时间不带毫秒
  5. * @ts 时间戳 如1548744604
  6. * @type 日期格式 如日期/时间/日期+时间
  7. */
  8. function getDateTime(ts, type) {
  9. // 转为字符串才有length属性
  10. var len = ts.toString().length;
  11. //证明是php以秒为单位的格式,需要转为JS单位
  12. if (len === 10) {
  13. ts = ts * 1000;
  14. }
  15. //获取年月日时分秒
  16. var dt = new Date(ts),
  17. y = dt.getFullYear(),
  18. //注意:month从0开始
  19. m = addZero(dt.getMonth() + 1),
  20. d = addZero(dt.getDate()),
  21. h = addZero(dt.getHours()),
  22. i = addZero(dt.getMinutes()),
  23. s = addZero(dt.getSeconds());
  24. switch (type) {
  25. case 'date':
  26. return y + '-' + m + '-' + d;
  27. break;
  28. case 'time':
  29. return h + ':' + i + ':' + s;
  30. break;
  31. case 'dateTime':
  32. return y + '-' + m + '-' + d + ' ' + h + ':' + i + ':' + s;
  33. break;
  34. default:
  35. return y + '-' + m + '-' + d + ' ' + h + ':' + i + ':' + s;
  36. }
  37. //把一位数字补齐为两位 格式为 1 -> 01
  38. function addZero(num) {
  39. return num < 10 ? ('0' + num) : num;
  40. }
  41. }

cookie

  1. /**
  2. * 封装cookie增删改查的函数
  3. */
  4. var manageCookies = {
  5. /**
  6. * 设置cookie属性及时间
  7. * 例如:document.cookie = 'name=xiaohong;max-age=1000'
  8. * 注意:只能逐条设置
  9. * @param {*} key 属性名
  10. * @param {*} value 属性值
  11. * @param {*} expTime 过期时间
  12. * @returns
  13. */
  14. set: function (key, value, expTime) {
  15. document.cookie = key + '=' + value + ';max-age=' + expTime;
  16. //实现链式调用
  17. return this;
  18. },
  19. /**
  20. * 删除cookie属性
  21. * 例如: document.cookie = 'name=xiaohong;max-age=-1'
  22. * @param {*} key 被删的属性
  23. */
  24. delete: function (key) {
  25. return this.set(key, '', -1);
  26. },
  27. /**
  28. * 查询cookie属性
  29. * 例如:document.cookie => 'hobby=basketball;sex=male;age=20'
  30. * 使用:get('hobby', function(data){console.log(data)})
  31. * @param {*} key
  32. * @param {*} cb
  33. * @returns
  34. */
  35. get: function (key, cb) {
  36. //将拿到的字符串用冒号分割成为数组
  37. //'hobby=basketball;sex=male;age=20'
  38. // => ['hobby=basketball','sex=male','age=20']
  39. var CookiesArray = document.cookie.split('; ');
  40. for (var i = 0; i < CookiesArray.length; i++) {
  41. var CookieItem = CookiesArray[i];
  42. //循环每一项并用等号分割
  43. //['hobby','basketball']
  44. //['sex','male']
  45. //['age','20']
  46. var CookieItemArray = CookieItem.split('=');
  47. if (CookieItemArray[0] == key) {
  48. cb(CookieItemArray[1]);
  49. return this;
  50. }
  51. }
  52. //如果没有cookie里面的属性报undefined
  53. cb(undefined);
  54. return this;
  55. }
  56. }

请求数据

在项目中多个API请求时统一管理

  1. //api > request.js
  2. //封装get请求函数
  3. const ERR_OK = 200;
  4. //柯里化的形式固定第一个参数
  5. //http://localhost:8080/area/info?name=广州市
  6. function getData(url) {
  7. return function (params) {
  8. return axios.get(url, params)
  9. .then(res => {
  10. const {
  11. status,
  12. data
  13. } = res;
  14. if (status === ERR_OK) {
  15. return data;
  16. }
  17. })
  18. .catch(e => {});
  19. }
  20. }
  21. export {
  22. getData
  23. }
  1. //api > index.js
  2. import {
  3. get
  4. } from './request';
  5. //它接收一个函数
  6. const getCityInfo = get('/area/info');
  7. export {
  8. getCityInfo
  9. }

url参数获取

获取url地址参数并返回一个对象参数

  1. //获取url地址参数
  2. function getUrlQueryParams(queryStr) {
  3. var result = {};
  4. //'?name=广州市&area=tianhe'
  5. //[?&]指的是以 ? 或 & 开头
  6. //[]指的是 一串非 ? 和 & 的字符 一个或多个
  7. // =
  8. var reg = /[?&][^?&]+=[^?&]+/g,
  9. found = queryStr.match(reg),
  10. tem,
  11. key,
  12. value;
  13. //['?name=广州市', '&area=tianhe']
  14. //有匹配结果时
  15. if (found) {
  16. found.forEach((item) => {
  17. //去除第一个字符 ? 或 &
  18. //以 = 隔开 拿到隔开后的数组 ['name', '广州市']
  19. tem = item.substring(1).split('=');
  20. key = tem[0];
  21. value = tem[1];
  22. result[key] = value;
  23. });
  24. }
  25. // console.log(result);
  26. //{name: '广州市', area: 'tianhe'}
  27. return result;
  28. }