自学内容网 自学内容网

工具类(util.js)

1. 圣杯模式继承

var inherit = (function(){
// 创建缓冲层
var Buffer = function(){};
/**
* target: 子类
* origin: 父类
**/
return function(Target, Origin){
// 实现继承
Buffer.prototype = Origin.prototype;
Target.prototype = new Buffer();
// 明确子类的构造器函数和继承的父类
Target.prototype.constructor = Target;
Target.super_class = Origin;
}
})();

2. 封装typeof函数

// 原生typeof函数返回值: number string boolean undefined object(null) function
function myTypeof(str) {
  var toStr = Object.prototype.toString,
      strType = typeof(str);
  // 设置结果集
      res = {
        '[object Object]':'[object Object]',
        '[object Array]':'[object Array]',
        '[object Boolean]':'[object Boolean]',
        '[object Number]':'[object Number]',
        '[object String]':'[object String]',
        '[object Date]':'[object Date]'
      };
 if(str === null) {
   return 'null';
 } else if(strType === 'object') {
   var newType = toStr.call(str);
   return res[newType];
 } else {
   return strType;
 }
}

3. 深拷贝


/**
* target:目标对象
* origin:源对象
**/
function deepClone(origin, target) {
    var target = target || {},
        toStr = Object.prototype.toString,
        arrType = '[object Array]';
  // for in 循环遍历origin对象
  for(var key in origin) {
    // 除去prototype上的自定义属性
    if(origin.hasOwnProperty(key)) {
      // 对属性类别进行判断
      if(typeof(origin[key]) === 'object' && origin[key] !== null) {
        // 引用类型数据
        if(toStr.call(origin[key]) === arrType) {
          // 数据类型是数组
          target[key] = [];
          // 递归克隆
          deepClone(origin[key], target[key]);
        } else {
          // 数据类型是对象
          target[key] = {};
          // 递归克隆
          deepClone(origin[key], target[key]);
        }
      } else {
        // 原始数据类型,直接进行拷贝
        target[key] = origin[key];
      }
    }
  }
  return target;
}

4. 获取子元素节点

// 获取子元素节点
Element.prototype.myChildren = function() {
var childNodes = this.childNodes,
childNodesLen = childNodes.length,
temp = {
'length':0,
'splice':Array.prototype.splice,
'push':Array.prototype.push
};
// 循环遍历节点,获取子节点
for(var i = 0; i < childNodesLen; i++) {
var item = childNodes[i];
// 判断是否是元素节点
if(item.nodeType === 1) {
// temp[temp['length']] = item[i];
// temp['length']++;
temp.push(item);
}
}
return temp;
}

5. 遍历任意一个父元素,找到它的子元素节点,有数字参数的话,就返回对应的子元素;没有数字参数,就返回子元素节点的集合。

Element.prototype.checkChildren = function(number) {
var childNodes = this.childNodes,
childNodesLen = childNodes.length,
temp = {
'length':0,
'splice':Array.prototype.splice,
'push':Array.prototype.push
};
// 对参数number进行判断,不是数字类型。
if(number !== undefined && typeof(number) !== 'number') {
return undefined;
}

return number === undefined ? filterChildren() : filterChildren()[number];

// 筛选父节点的所有子节点元素
function filterChildren() {
for(var i = 0; i < childNodesLen; i++) {
var item = childNodes[i];
if(item.nodeType === 1) {
// temp[temp['length']] = item[i];
// temp['length']++;
temp.push(item);
}
}
return temp;
}
}

6. 找出一个元素的第N层父级元素。

// html的父级元素是null;

Element.prototype.parentNth = function(number) {
var type = typeof(number),
elem = this;
// 处理参数number
if(number === undefined || type !== 'number') {
// 如果参数不传 || undefined || 不是数字类型
return elem.parentNode;
} else if(number < 0) {
// 如果参数numbe小于0
return undefined;
} 
// 参数number符合需求
while(number) {
if(elem.nodeName === 'HTML') {
return null;
}
elem = elem.parentNode;
number--;
}
return elem;
}

7. 判断父节点是否存在子元素节点。

Element.prototype.hasChildrenElement = function() {
var childNodes = this.childNodes,
childNodesLen = childNodes.length,
item;
//循环遍历父级节点下的子节点
for(var i = 0; i < childNodesLen; i++) {
item = childNodes[i];
if(item.nodeType === 1) {
return true;
}
}
return false;
}

8. 寻找兄弟元素节点,传递参数N,N>0找之后第N个兄弟元素节点;N<0找之前的第N个。

// 上一个兄弟节点: element.previousSibling
// 下一个兄弟节点: element.nextSibling

Element.prototype.brotherElementNode = function(number) {
var elem = this,
type = typeof(number),
parentNode = elem.parentNode,
parentChildNodes = parentNode.childNodes,
parentChildNodesLen = parentChildNodes.length;
// 处理参数number
if(type === 'undefined' || type !== 'number') {
return undefined;
} 
if(number > 0) {
return getBrotherElement(elem, number);
} else if(number < 0) {
return getBrotherElement(elem, number);
}
// number === 0;
return elem;

// 获取兄弟元素节点
function getBrotherElement(elem, number) {
var temp = {
'length':0,
'splice':Array.prototype.splice,
'push':Array.prototype.push,
'indexOf':Array.prototype.indexOf
},
index = 0;
for(var i = 0; i < parentChildNodesLen; i++) {
var item = parenChildNodes[i];
if(item.nodeType === 1) {
temp.push(item);
}
}
index = temp.indexOf(elem);
return number === 0 ? temp[index] : temp[index + number];
}
}

9. 寻找兄弟元素节点,传递参数N,N>0找之后第N个兄弟元素节点;N<0找之前的第N个。

// 上一个兄弟元素节点:previousElementSibling
// 下一个兄弟元素节点:nextElementSibling

// 第一种:
Element.prototype.brotherNode = function (n) {
var elem = this;
while(n) {
if(n > 0) {
if(elem.nextElementSibling) {
elem = elem.nextElementSibling;
} else {
for(elem = elem.nextSibling; elem && elem.nodeType !== 1; elem = elem.nextSibling);
}
n--;
} else {
for(elem = elem.previousSibling; elem && elem.nodeType !== 1; elem = elem.previousSibling);
}
n++;
}
return elem;
}

// 第二种:
Element.prototype.brotherNode = function (n) {
var elem = this;
while(n) {
if(n > 0) {
elem = elem.nextSibling;
while(elem && elem.nodeType !== 1) {
elem = elem.nextSibling;
}
n--;
} else if(n < 0) {
elem = elem.previousSibling;
while(elem && elem.nodeType !== 1) {
elem = elem.previousSibling;
}
n++;
}
}
return elem;
}

10. 遍历一个父级元素下面所有的元素节点

// 第一种(不包括父级元素)
Element.prototype.childrenElementNode = function(arr) {
var elem = this,
childNodes = elem.childNodes,
childNodeLen = elem.childNodes.length,
temp = arr || {
'length':0,
'splice':Array.prototype.splice,
'push':Array.prototype.push
};
// 循环遍历childNodes,寻找子元素节点
for(var i = 0; i < childNodeLen; i++) {
var item = childNodes[i];
if(item.nodeType === 1) {
temp.push(item);
// 递归循环遍历子元素节点
item.childrenElementNode(temp);
}
}
}

// 第二种(包括父级元素)
function getFullChildren(node) {
var children = node.childNodes,
childrenLen = children.length,
item;
if(node && node.nodeType === 1) {
console.log(node);
}
for(var i = 0; i < childrenLen; i++) {
item = children[i];
if(item.nodeType === 1) {
getFullChildren(item);
}
}
}

11. 原型上封装insertAfter方法

// parent.insertBefore(newNode, refereneceNode)方法:在父级元素的referenceNode子元素之前插入newNode节点。

/**
* newNode:需要插入的节点
* referenceNode:参考节点
**/
Element.prototype.insertAfter = function(newNode, referenceNode) {
var refNextNode = referenceNode.nextSibling;
// 判断参考节点是否还存在兄弟元素节点
while(refNextNode){
// 存在兄弟元素节点
if(refNextNode.nodeType === 1) {
return this.insertBefore(newNode, refNextNode);
}
refNextNode = refNextNode.nextSibling;
}
// 不存在兄弟元素节点, refNextNode是最后一个子元素节点
this.appendChild(newNode);
}

12. DOM结构树倒序

function revese(node) {
var children = node.childNodes,
childrenLen = children.length;
while(childrenLen) {
childrenLen--;
node.appendChild(children[childrenLen]);
}
}

13. 获取滚动条的兼容写法

// 常规获取:window.pageYOffset;
// IE9 / IE8及以下获取: document.body.scrollTop + document.documentElement.scrollTop;

function getScrollOffset() {
if(window.pageXOffset) {
return {
x: window.pageXOffset,
y: window.pageYOffset
}
} else {
return {
x: document.body.scrollLeft + document.documentElement.scrollLeft,
y: document.body.scrollTop + document.documentElement.scrollTop
}
}
}

14. 获取浏览器的可视窗口宽和高兼容写法

// 获取文档的模式: document.compatMode
// 标准模式: CSS1Compat
// 怪异模式: BackCompat

function getViewportSize() {
if(window.innerWidth) {
return {
x: window.innerWidth, (包括滚动条)
y: window.innerHeight
}
} else {
// IE9 / IE8及以下
if(document.compatMode === 'BackCompat') {
// 怪异模式
return {
x: document.body.clientWidth, (不包括滚动条)
y: document.body.clientHeight
}
// IE9 / IE8及以下
} else {
// 标准模式
return {
x: document.documentElement.clientWidth, (不包括滚动条)
y: document.documentElement.clientHeight
}
}
}
}

15. 获取文档的宽和高兼容写法

function getDocSize() {
if(document.body.scrollWidth) {
return {
x: document.body.scrollWidth,
y: document.body.scrollHeight
}
} else {
return {
x: document.documentElement.scrollWidth,
y: document.documentElement.scrollHeight
}
}
}

16. 封装offsetLeft和offsetTop兼容写法

// 获取元素距离HTML的距离,offsetLeft / offsetTop相对于父级定位元素。
// 获取父级的定位元素:offsetParent属性。

function getElemDocPosition(elem) {
// 父级定位元素
var parentPos = elem.offsetParent,
offsetLeft = parentPos.offsetLeft,
offsetTop = parentPos.offsetTop;
if(elem.nodeName === 'HTML') {
return {
offsetLeft: 0,
offsetTop: 0
}
}
while(parentPos) {
parentLeft += parentPos.offsetLeft;
parentTop += parentPos.offsetTop;
parentPos = parentPos.offsetParent;
}
return {
offsetLeft: parentOffX,
offsetTop: parentOffY
}
}

17. 获取计算样式方法window.getComputedStyle()封装兼容写法

// 正常获取:window.getComputedStyle(elem, null)[prop];
// IE8及以下获取: elem.currentStyle[prop];

function getStyle(elem, prop) {
if(window.getComputedStyle) {
if(prop) {
return window.getComputedStyle(elem, null)[prop];
} else {
return window.getComputedStyle(elem, null);
}
} else {
if(prop) {
return elem.currentStyle[prop];
} else {
return elem.currentStyle;
}
}
}

18. 绑定事件的监听兼容写法

// 常用方式:addEventListener 
// IE8及以下:attachEvent
// 兼容性最好:onclick

function addEvent(elem, type, fn) {
if(elem.addEventListener) {
elem.addEventListener(type, fn, false);
} else if(elem.attachEvent) {
elem.attachEvent('on'+ type, function(){
// this指向window,改变this指向
fn.call(elem);
});
} else {
elem['on' + type] = fn;
}
}

19. 解除事件的监听兼容写法

// addEventListener: removeEventListener
// attachEvent: detachEvent
// onclick: onclick = null / false;

function removeEvent(elem, type, fn) {
if(elem.removeEventListener) {
elem.removeEventListener(type, fn, false);
} else if(elem.detachEvent) {
elem.detachEvent('on' + type, fn);
} else {
// elem['on' + type] = null;
elem['on' + type] = false;
}
}

20. 取消冒泡的兼容写法

// propagation 传播

function cancleBublle(event) {
var event = event || window.event;
if(event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBublle = true;
}
}

21. 取消默认事件的兼容性写法

// return false;
// w3c规范: preventDefault; // IE9不兼容
// returnValue: false; // IE9不兼容
function cancleDefaultEvent(event) {
var event = event || window.event;
if(event.preventDefault) {
event.preventDefault();
} else if(event.returnValue) {
  event.returnValue = false;
} else {
return false;
}
}

22. 鼠标坐标系pageX / pageY封装

function posPage(e) {
  var e = e || window.event,
      sLeft = getScrollLeft().x,
      sTop = getScrollTop().y,
      cLeft = document.documentElement.clientLeft || 0,
      cTop = document.documentElement.clientTop || 0;
  return {
    x: e.clientX + sLeft - cLeft,
    y: e.clientY + sTop - cTop
  }
}

23. 封装拖拽函数

function elemDrag(elem) {
var x,
y;
// 添加事件处理函数
addEvent(elem, 'mousedown', function(e){
var e = e || window.event,
clientX = posPage(e).X - parseInt(getStyle(elem, 'left')),
clientY = posPage(e).Y - parseInt(getStyle(elem, 'top'));
// 添加鼠标移动的事件
addEvent(document, 'mousemove', mouseMove);
// 添加鼠标抬起的事件
addEvent(document, 'mouseup', mouseUp);
// 鼠标滑动事件
function mouseMove(e) {
var e = e || window.event,
x = posPage(e).X - clientX,
y = posPage(e).Y - clientY;
elem.style.left = x + 'px';
elem.style.top = y + 'px';
}
// 鼠标抬起事件
function mouseUp(e){
var e = e || window.event;
// 取消监听事件
removeEvent(document, 'mousemove', mouseMove);
removeEvent(document, 'mouseup', mouseUp);
}
// (防止出现意外,取消冒泡事件,阻止默认行为)
cancleBublle(e);
cancleDefaultEvent(e);
});
}

24. AJAX的封装

// 模块化封装原生AJAX
// 因为jquery中的AJAX调用形式$.get,$.post,$.Ajax,所以我们也按照这样的样式进行封装
var $ = (function () {
function _doAjax(opt) {
// 首先兼容性写法
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
// 如果浏览器不支持AJAX请求
if (!xhr) {
throw new Error('您的浏览器不支持AJAX请求数据!请更新后再试~');
}
// 请求方法,防止用户传入小写,强制转化为大写
var method = (opt.method || 'GET').toUpperCase(),
// 请求地址
url = opt.url,
// 同步请求or异步请求
async = '' + opt.async === 'false' ? false : true,
// 请求参数
data = opt.data || null,
// 响应返回后的数据格式
dataType = opt.dataType || 'JSON',
// jsonp跨域
jsonp = opt.jsonp || 'cb',
jsonpCallback = opt.jsonpCallback || 'jQuery' + randomNum() + '_' + new Date().getTime(),
// 成功后的回调函数
success = opt.success || function () { },
// 失败后的回调函数
error = opt.error || function () { },
// 无论失败还是成功都会执行的complete函数
complete = opt.complete || function () { },
// 设置超时时间
timeout = opt.timeout || 5000,
// 设置定时器
t = null;
// 未传入url
if (!url) {
throw new Error('未传入url参数');
}
if (dataType.toUpperCase() === 'JSONP' && method !== 'GET') {
throw new Error('如果dataType为JSONP,请您将type设置成GET');
}
// JSONP跨域逻辑
if (dataType.toUpperCase() === 'JSONP') {
var oScript = document.createElement('script');
// xxx.domain.com/xxx.php?cb=test
// xxx.domain.com/xxx.php?wd=xxx&cb=test
oScript.src = url.indexOf('?') === -1
? url + '?' + jsonp + '=' + jsonpCallback
: url + '&' + jsonp + '=' + jsonpCallback;
document.body.appendChild(oScript);
document.body.removeChild(oScript);
window[jsonpCallback] = function (data) {
success(data);
}
return;
}
// AJAX绑定事件监听处理函数
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
switch (dataType.toUpperCase()) {
case 'JSON':
success(JSON.parse(xhr.responseText));
break;
case 'XML':
success(xhr.responseXML);
break;
case 'TEXT':
success(xhr.responseText);
break;
default:
success(JSON.parse(xhr.responseText));
break;
}
} else {
error();
}
// 请求成功,清除定时器
clearTimeout(t);
t = null;
xhr = null;
// 最后执行complete函数
complete();
}
}
// 处理AJAX请求的逻辑
xhr.open(method, url, async);
// POST请求设置请求头数据的格式类型
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// 处理请求数据中的data格式
xhr.send(method === 'GET' ? null : dataFormat(data));

// 设置超时设置
t = setTimeout(function () {
xhr.abort();
clearTimeout(t);
t = null;
xhr = null;
throw new Error('请求超时,请稍后重试!');
}, timeout)
}

function dataFormat(data) {
// {'name':'Tom','sex':'male'} ---> 'name=Tom&sex=male'
// 循环对象
var str = '';
for (var key in data) {
// 只遍历对象本身的属性
if (data.hasOwnProperty(key)) {
str += key + '=' + data[key] + '&';
}
}
return str.replace(/&$/, '');
}

function randomNum() {
var str = '';
for (var i = 0; i < 20; i++) {
str += Math.floor(Math.random() * 10);
}
return str;
}

return {
Ajax: function (opt) {
// 处理传入的参数问题,抽离函数,能够让所有方法能够在Ajax方法外处理
_doAjax(opt);
},
post: function (url, data, timeout, dataType, successCB, errorCB, completeCB) {
_doAjax({
method: 'POST',
url: url,
data: data,
dataType: dataType,
timeout: timeout,
success: successCB,
error: errorCB,
complete: completeCB
});
},
get: function (url, data, timeout, dataType, successCB, errorCB, completeCB) {
_doAjax({
method: 'GET',
url: url,
data: data,
timeout: timeout,
dataType: dataType,
success: successCB,
error: errorCB,
complete: completeCB
});
}
}
})();

// domain跨域
var ajaxDomain = (function () {
// 创建iframe元素
function createIframe(frameId, frameUrl) {
var iframe = document.createElement('iframe');
iframe.src = frameUrl;
iframe.id = frameId;
iframe.style.display = 'none';
return frame;
}
// 实现跨域
return function (opt) {
// 设置当前服务器的域名
document.main = opt.basicDomain;
var iframe = createIframe(opt.frameId, opt.frameUrl);
iframe.onload = function () {
// 获取与api同源子级页面中的ajax
var $$ = document.getElementById(opt.frameId).contentWindow.$;
// 请求数据
$$.ajax({
url: opt.url,
method: opt.method,
data: opt.data,
success: opt.success,
error: opt.error
})
}
document.body.appenChild(iframe);
}
})();

25. Cookie的封装

var manageCookie = {
// 设置cookie
set:function(key, value, expTime){
document.cookie = key + '=' + value + '; ' + 'max-age=' + expTime;
// 链式调用
return this;
},
// 获取cookie
get:function(key, callback){
var cookiesArray = document.cookie.split('; ');
for(var i = 0; i < cookiesArray.length; i++) {
var cookieItem = cookiesArray[i];
var cookieItemArray = cookieItem.split('=');
if(cookieItemArray[0] === key) {
// 回调函数功能扩展
callback(cookieItemArray[1]);
return this
}
}
callback(undefined);
return this;
},
// 删除cookie
delete:function(key){
return this.set(key, '', -1);
}
}

26.节流函数

var oInput = document.querySelector('.J_Input_Node');

oInput.addEventListener('input', throttle(changeInputValue, 1000), false);

// 节流函数
function throttle(throttleFn, delay) {
var startTime = new Date().getTime();
return function () {
var endTime = new Date().getTime(),
distance = endTime - startTime;
if (distance >= delay) {
// 允许触发
throttleFn.call(this);
startTime = endTime;
}
}
}

// 一定间隔内减少触发的次数
function changeInputValue() {
console.log(this.value);
}

原文地址:https://blog.csdn.net/IT_Mr_wu/article/details/137103645

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!