自学内容网 自学内容网

工具类(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)!