原生js实现 常见的jquery的功能
节点操作
1 2 3 4 5 | var div2 = document.querySelector("#div2"); div2.insertAdjacentHTML("beforebegin","< p >hello world</ p >");//在调用元素外部前面添加一个元素 div2.insertAdjacentHTML("afterbegin","< p >hello world</ p >");//在调用元素的内部添加一个子元素并取代了第一个子元素 div2.insertAdjacentHTML("beforeend","< p >hello world</ p >");//在调用元素内部后面添加一个子元素 即取代了最后的子元素 div2.insertAdjacentHTML("afterend","< p >hello world</ p >");//在调用元素的外部后面添加一个元素 |
1 2 3 4 5 | var bes=document.getElementById("appends"), var strs= "< li >234</ li >"; bes.insertAdjacentHTML('beforebegin', strs); |
extend 普通深拷贝
function extend() { var length = arguments.length; var target = arguments[0] || {}; if (typeof target!="object" && typeof target != "function") { target = {}; } if (length == 1) { target = this; i--; } var hasOwn=Object.prototype.hasOwnProperty; for (var i = 1; i < length; i++) { var source = arguments[i]; for (var key in source) { // 使用for in会遍历数组所有的可枚举属性,包括原型。 if (hasOwn.call(source, key)) { target[key] = source[key]; } } } return target; }
1 2 3 | var obj1 = {'a': 'obj2','b':'2'}; var obj2 = {name: 'obj3'}; console.log('extend',extend({},obj1,obj2),'obj1',obj1,'obj2',obj2); |
jquery 深拷贝
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | function isArray(value) { return Array.isArray(value) || Object.prototype.toString.call(value) === '[object Array]'; } function isFunction(fn) { return Object.prototype.toString.call(fn) === "[object Function]"; } function isPlainObject(value) { if (typeof value !== 'object' || value === null) { return false } if (Object.getPrototypeOf(value) === null) { return true } var proto = value while (Object.getPrototypeOf(proto) !== null) { proto = Object.getPrototypeOf(proto) } return Object.getPrototypeOf(value) === proto } function myExtend() { var src, copyIsArray, copy, name, options, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if (typeof target === "boolean") { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) if (typeof target !== "object" && !isFunction(target)) { target = {}; } // extend jQuery itself if only one argument is passed if (length === i) { target = this; --i; } for (; i < length; i++) { // Only deal with non-null/undefined values if ((options = arguments[i]) != null) { // Extend the base object for (name in options) { src = target[name]; copy = options[name]; // Prevent never-ending loop if (target === copy) { continue; } // Recurse if we're merging plain objects or arrays if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { if (copyIsArray) { copyIsArray = false; clone = src && isArray(src) ? src : []; } else { clone = src && isPlainObject(src) ? src : {}; } // Never move original objects, clone them target[name] = myExtend(deep, clone, copy); // Don't bring in undefined values } else if (copy !== undefined) { target[name] = copy; } } } } // Return the modified object return target; } |
var obj1 = { a: 1, name: "张珊", title: { text: 'hello world', subtext: 'It/s my world.' } }; var obj2 = { a: 2, name: "李四", title: { subtext: 'Yes, your world.' } } //var obj3= {...{},...obj1,...obj2 } // Object.assign(目标对象,...源对象)可以有多个源对象 //var obj3 =Object.assign({},obj1,obj2) //var obj3= myExtend({},obj1,obj2) //console.log("$",$.version) //var obj3= $.extend(true,{},obj1,obj2) //var obj3= myExtend({},obj1,obj2) var obj3 = myExtend2({}, obj1, obj2) obj3.name = '王五' console.log("obj1", obj1); console.log("obj2", obj2); console.log("obj3", obj3, "title", obj3.title);
去掉JSON 中的 "undefined","null" 等字符串
function deleteEmptyProp(opt,delArr,del) { var delArr=delArr||["undefined","null",undefined,null,NaN]; for (var key in opt) { var val=opt[key]; if (delArr.includes(val)) { if(del){ delete opt[key]; }else{ var isValueNaN= (typeof val === 'number')&&(val !== val)?1:0;//判断NaN ,替换成0 if(isValueNaN){ opt[key]=0; }else{ opt[key]=""; } } } } return opt; }
var sas={a: 'duo', b: 0, c: null,d:"null",e:"undefined",f:NaN,g:undefined}
console.log((deleteEmptyProp(sas)))
var sas2={a: 'duo', b: 0, c: null,d:"null",e:"undefined",f:NaN,g:undefined,h:"NaN"}
console.log(deleteEmptyProp(sas2,["undefined","null",undefined,null,NaN]))
合理化 字符串
// "true" => true // "false" => false // "null" => null // "42" => 42 // "42.5" => 42.5 // "08" => "08" // JSON => parse if valid // String => self function deserializeValue(value) { var num try { return value ? value == "true" || ( value == "false" ? false : value == "null" ? null : !/^0/.test(value) && !isNaN(num = Number(value)) ? num : /^[\[\{]/.test(value) ? $.parseJSON(value) : value ) : value } catch(e) { return value } }
原生选择器 $('#box') 利用 bind(this)绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | < div id="box"> < ul > < li >111 </ li > < li class="lione">2222</ li > < li class="lione">3333</ li > </ ul > </ div > < div id="box2"> < p >我是AAAA</ p > < p >我是BBBB</ p > </ div > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //选择器的实现 var element = document.querySelector( 'selectors' ); var elementList = document.querySelectorAll( 'selectors' ); var $=query = document.querySelector.bind(document); var queryAll = document.querySelectorAll.bind(document); //这个是最牛逼的 细细体会就会发现 var fromId = document.getElementById.bind(document); var fromClass = document.getElementsByClassName.bind(document); var fromTag = document.getElementsByTagName.bind(document); //调用 var box=$( '#box' ); var lioneall=queryAll( 'li' ); var lione=$( '.lione' ); console.log(box.innerHTML); // console.log(lioneall[2].innerHTML); //333 box.addEventListener( 'click' , function (){ console.log( 'click lione' +lione.innerHTML); //click lione 2222 }); |
另一个不错的 https://github.com/snandy/zchain/blob/master/%24/selector.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | /** * JavaScript Selector * Copyright (c) 2010 snandy * Blog: http://snandy.cnglogs.com * QQ群: 34580561 * * $ 获取元素, 在DOM中使用频繁的,根据2/8原则只实现最常用的四种 * * @param {Object} selector * @param {Object} context * * 1, 通过id获取,该元素是唯一的 * $('#id') * * 2, 通过className获取 * $('.cls') 获取文档中所有className为cls的元素 * $('.cls', el) * $('.cls', '#id') * $('span.cls') 获取文档中所有className为cls的span元素 * $('span.cls', el) 获取指定元素中className为cls的元素, el为HTMLElement (不推荐) * $('span.cls', '#id') 获取指定id的元素中className为cls的元素 * * 3, 通过tagName获取 * $('span') 获取文档中所有的span元素 * $('span', el) 获取指定元素中的span元素, el为HTMLElement (不推荐) * $('span', '#id') 获取指定id的元素中的span元素 * * 4, 通过attribute获取 * $('[name]') 获取文档中具有属性name的元素 * $('[name]', el) * $('[name]', '#id') * $('[name=uname]') 获取文档中所有属性name=uname的元素 * $('[name=uname]', el) * $('[name=uname]', '#id') * $('input[name=uname]') 获取文档中所有属性name=uname的input元素 * $('input[name=uname]', el) * $('input[name=uname]', '#id') */ ~ function (win, doc, undefined) { // Save a reference to core methods var slice = Array.prototype.slice // selector regular expression var rId = /^ #[\w\-]+/ var rTag = /^([\w\*]+)$/ var rCls = /^([\w\-]+)?\.([\w\-]+)/ var rAttr = /^([\w]+)?\[([\w]+-?[\w]+?)(=(\w+))?\]/ // For IE9/Firefox/Safari/Chrome/Opera var makeArray = function (obj) { return slice.call(obj, 0) } // For IE6/7/8 try { slice.call(doc.documentElement.childNodes, 0)[0].nodeType } catch (e) { makeArray = function (obj) { var result = [] for ( var i = 0, len = obj.length; i < len; i++) { result[i] = obj[i] } return result } } function byId(id) { return doc.getElementById(id) } function check(attr, val, node) { var reg = RegExp( '(?:^|\\s+)' + val + '(?:\\s+|$)' ) var attribute = attr === 'className' ? node.className : node.getAttribute(attr) if (attribute) { if (val) { if (reg.test(attribute)) return true } else { return true } } return false } function filter(all, attr, val) { var el, result = [] var i = 0, r = 0 while ( (el = all[i++]) ) { if ( check(attr, val, el) ) { result[r++] = el } } return result } function query(selector, context) { var s = selector, arr = [] var context = context === undefined ? doc : typeof context === 'string' ? query(context)[0] : context if (!selector) return arr // id和tagName 直接使用 getElementById 和 getElementsByTagName // id if ( rId.test(s) ) { arr[0] = byId( s.substr(1, s.length) ) return arr } // Tag name if ( rTag.test(s) ) { return makeArray(context.getElementsByTagName(s)) } // 优先使用querySelector,现代浏览器都实现它了 if (context.querySelectorAll) { if (context.nodeType === 1) { var old = context.id, id = context.id = '__ZZ__' try { return context.querySelectorAll( '#' + id + ' ' + s) } catch (e) { throw new Error( 'querySelectorAll: ' + e) } finally { old ? context.id = old : context.removeAttribute( 'id' ) } } return makeArray(context.querySelectorAll(s)) } // ClassName if ( rCls.test(s) ) { var ary = s.split( '.' ) var tag = ary[0] var cls = ary[1] if (context.getElementsByClassName) { var elems = context.getElementsByClassName(cls) if (tag) { for ( var i = 0, len = elems.length; i < len; i++) { var el = elems[i] el.tagName.toLowerCase() === tag && arr.push(el) } return arr } else { return makeArray(elems) } } else { var all = context.getElementsByTagName(tag || '*' ) return filter(all, 'className' , cls) } } // Attribute if ( rAttr.test(s) ) { var result = rAttr.exec(s) var all = context.getElementsByTagName(result[1] || '*' ) return filter(all, result[2], result[4]) } } win.query = win.$ = query }( this , document); |
offset 函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | var myOffest= function (obj){ var top=0,left=0; if (obj){ while (obj.offsetParent){ top += obj.offsetTop; left += obj.offsetLeft; obj = obj.offsetParent; } } return { top : top, left : left } } |
1 2 3 4 5 6 | var jqtop=jQuery( '#box2' ).offset().top; console.log( 'jQuery offsetTop 值' +jqtop); // jQuery offsetTop 值274 var jstop=document.getElementById( "box2" ); console.log( 'js offsetTop 值' +myOffest(jstop).top); // js offsetTop 值274 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | getOffset2(node){ var offest = { top: 0, left: 0 }; // 当前为IE11以下, 直接返回{top: 0, left: 0} if (!node.getClientRects().length) { return offest; } // 当前DOM节点的 display === 'node' 时, 直接返回{top: 0, left: 0} if (window.getComputedStyle(node)[ 'display' ] === 'none' ) { return offest; } // Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。 // 返回值包含了一组用于描述边框的只读属性——left、top、right和bottom,单位为像素。除了 width 和 height 外的属性都是相对于视口的左上角位置而言的。 // 返回如{top: 8, right: 1432, bottom: 548, left: 8, width: 1424…} offest = node.getBoundingClientRect(); var docElement = node.ownerDocument.documentElement; return { top: offest.top + window.pageYOffset - docElement.clientTop, left: offest.left + window.pageXOffset - docElement.clientLeft }; } |
offset限定父类范围
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function myOffest(obj,parentObj){ var top=0,left=0; if(obj){ while(obj.offsetParent){ if(parentObj&&obj&&obj.className.indexOf(parentObj)!=-1){ break; } left += obj.offsetLeft; obj = obj.offsetParent; } } //console.log("222 55 最后obj---",obj) return{ left : left } } |
getOffsetParent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | function getOffsetParent(element) { // NOTE: 1 DOM access here var offsetParent = element && element.offsetParent; var nodeName = offsetParent && offsetParent.nodeName; if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') { if (element) { return element.ownerDocument.documentElement; } return window.document.documentElement; } // .offsetParent will return the closest TD or TABLE in case // no offsetParent is present, I hate this job... //console.log("window.getComputedStyle(offsetParent, null).position",window.getComputedStyle(offsetParent, null).position) if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 &&window.getComputedStyle(offsetParent, null).position=== 'static') { return getOffsetParent(offsetParent); } return offsetParent; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | function getOffsetParent(elem) { var doc = elem.ownerDocument||document; var offsetParent = elem.offsetParent ; //console.log(elem,"offsetParent",offsetParent) var position= offsetParent&&window.getComputedStyle(offsetParent)[ "position" ] while (offsetParent &&(offsetParent.nodeName !== 'HTML' ) &&position=== "static" ) { offsetParent = offsetParent.offsetParent; } var last=offsetParent|| doc.documentElement; return offsetParent|| doc.documentElement; } |
//https://github.com/jquery/jquery/blob/main/src/offset.js
get_position
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | function get_position(elem) { var offsetParent, offset, elem = elem, parentOffset = { top: 0, left: 0 }; // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, // because it is its only offset parent if (window.getComputedStyle(elem)[ 'position' ] === "fixed" ) { // Assume getBoundingClientRect is there when computed position is fixed offset = elem.getBoundingClientRect(); } else { // Get *real* offsetParent offsetParent =getOffsetParent(elem); // console.log("offsetParent nodeName",offsetParent.nodeName) //console.log("eaas",eaas) // console.log("offsetParent2",offsetParent2) // Get correct offsets offset = getOffest(elem); if ( offsetParent.nodeName != "html" ) { parentOffset =getOffest(offsetParent);; } var borderTopWidth=window.getComputedStyle(offsetParent)[ 'borderTopWidth' ]||0; var borderLeftWidth=window.getComputedStyle(offsetParent)[ 'borderLeftWidth' ]||0; // Add offsetParent borders parentOffset.top += parseFloat(borderTopWidth); parentOffset.left += parseFloat(borderLeftWidth) ; // Subtract parent offsets and element margins // 可以看出,$().position()的本质是目标元素的offset()减去父元素的offset(),同时还要算上目标元素的margin,因为盒子模型(关键)。 //(注意:offset()的本质是getBoundingClientRect()的top、left + pageYOffset、pageXOffset) } // Subtract parent offsets and element margins var marginTop=window.getComputedStyle(elem)[ 'marginTop' ]||0; var marginLeft=window.getComputedStyle(elem)[ 'marginLeft' ]||0; console.log(marginTop, "marginLeft" ,marginLeft) var top2=parseFloat(offset.top||0) - parseFloat(parentOffset.top||0) - parseFloat(marginTop) ; var left2=parseFloat(offset.left||0) - parseFloat(parentOffset.left||0) - parseFloat(marginLeft) return { top: top2 , left: left2 }; } |
setOffset
function setOffset(elem,props,pixel){ var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition; //console.log("setOffset---",elem) //获取元素的position属性的值 var position =window.getComputedStyle(elem)['position']; if ( position === "static" ) { elem.style.position = "relative"; } //{left:8,top:16} curOffset = getOffest(elem);; //0px curCSSTop = window.getComputedStyle(elem)['top']||0;; //0px curCSSLeft = window.getComputedStyle(elem)['left']||0; calculatePosition = ( position === "absolute" || position === "fixed" ) &&( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1; if (calculatePosition ) { // curPosition = elem.position(); curPosition = get_position(position); curTop = parseFloat(curPosition.top)|| 0; curLeft= parseFloat(curPosition.left)|| 0; } else { //0 0 curTop = parseFloat( curCSSTop ) || 0; curLeft = parseFloat( curCSSLeft ) || 0; } //解析: //(1)先判断当前元素的 position 的值,没有设置 position 属性的话,默认为 relative,并获取元素的 top、left 属性的值 //(2)返回一个对象 obj,obj 的 top 是参数的 top - 默认偏移(offset)的 top + position 设置的 top(没有设置,默认为0),obj 的 left 同理。 // 也就是说 offset({top:15,;eft:15}) 的本质为: // 参数的属性减去对应的默认offset属性加上position上的对应属性。 //如果传的参数的有top值 //参数 top - offset().top + element.top var top = ( props.top - parseFloat(curOffset.top) ) + curTop; //参数 left - offset().left + element.left var left = ( props.left - parseFloat(curOffset.left) ) + curLeft; var pixel=pixel||"px" //console.log("top",top,'left',left) elem.style.top= top+pixel; elem.style.left= left+pixel; }
setOffset(p2,{top:200,left:position.left})
$(".p1").offset({top:200,left:position.left});
getOffsetRect 获取大小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function getOffsetRect(element) { var elementRect = { width: element.offsetWidth, height: element.offsetHeight, left: element.offsetLeft, top: element.offsetTop }; elementRect.right = elementRect.left + elementRect.width; elementRect.bottom = elementRect.top + elementRect.height; // 位置 return elementRect; } |
找到指定父类元素
1 2 3 4 5 6 7 8 9 | function getParent(element, className, limitClasss) { var nowName = element.getAttribute("class") || ""; var isFind = nowName && nowName.indexOf(className) !== -1 || limitClasss && nowName && nowName .indexOf(limitClasss) !== -1; if (isFind || !element.parentNode) { return element; // 已达到文档根元素,未找到指定父元素 } return getParent(element.parentNode, className); // 继续向上查找 } |
找到子元素在父元素的索引值
1 2 3 4 5 6 7 8 9 | function getChildIndex(child) { var parent = child.parentNode; for (var i = 0; i < parent.children.length; i++) { if (parent.children[i] === child) { return i; } } return -1; // 如果找不到子元素,返回-1 } |
var liEle = getParent(target, 'li-item', 'ul-item');
var liIndex = 0;
if (liEle) {
liIndex = getChildIndex(liEle);
console.log("liIndex", liIndex)
}
数组 forEach的实现
var unboundForEach = Array.prototype.forEach,forEach = Function.prototype.call.bind(unboundForEach);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <div id= "box3" > <p class = "klasses" >one</p> <p class = "klasses" >two</p> <p class = "klasses" >three</p> </div> <script> var unboundForEach = Array.prototype.forEach,forEach = Function.prototype.call.bind(unboundForEach); var box3=document.getElementById( "box3" ); var klasses=document.querySelectorAll( '.klasses' ) forEach(klasses, function (el) { el.addEventListener( 'click' , function (){ alert( '点击我的序号' + this .innerHTML); //点击我的序号 one }); }); </script> |
jquery的静态方法 $.each
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | function jQueryEach(object, callback, args) { var name, i = 0, length = object.length; if (args) { if (length == undefined) { for (name in object) { if (callback.apply(object[name], args) === false ) { break } } } else { for (; i < length;) { if (callback.apply(object[i++], args) === false ) { break } } } } else { if (length == undefined) { for (name in object) { if (callback.call(object[name], name, object[name]) === false ) { break } } } else { for ( var value = object[0]; i < length && callback.call(value, i, value) !== false ; value = object[++i]) {} } } return object }; |
1 2 3 4 5 6 7 8 9 10 11 | var arr1 = [ "one" , "two" , "three" , "four" , "five" ]; jQueryEach(arr1, function (index){ console.log(arr1[index]); // alert(this) }); var obj = { one: '张珊' , two: '李四' , three:3, four:4, five: '王五' }; jQueryEach(obj, function (key, val) { console.log( 'val' +obj[key]); }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Array.prototype.forEach2= function (fun,context){ var len= this .length; var context=arguments[1]; //即使为undefined,call函数也正常运行。 if ( typeof fun !== "function" ){ throw "输入正确函数!" ; } for ( var i=0;i<len;i++){ fun.apply(context,[i, this [i], this ]); //fun.call(context,i,this[i],this); } }; var arr2=[5,6,7]; //arr.forEach2(function(item,index,arr){ //console.log(item,index,arr); //}); |
hover 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | <!doctype html> <html> <head> <meta charset= "utf-8" > <title>无标题文档</title> </head> <body> 运行以下代码,正好就是jquery的hover方法 <div id= "dd" style= "width:100px; height:100px; border:1px solid #3d3d3d; position:relative;" > <div id= "dd2" style= "width:50px; height:50px; overflow:hidden; background-color:#cccccc; position:absolute; left:30px; top:30px;" ></div> </div> <script language= "javascript" > function bind(elem,ev,callback) { if (document.all) { elem.attachEvent( "on" +ev,callback); } else { elem.addEventListener(ev,callback, false ); } } function unbind(elem,ev,callback) { if ( typeof (callback)== "function" ) { if (document.all) { elem.detachEvent( "on" +ev,callback); } else { elem.removeEventListener(ev,callback, false ); } } else { if (document.all) { elem.detachEvent( "on" +ev); } else { elem.removeEventListener(ev, false ); } } } function hover(elem,overCallback,outCallback){ //实现hover事件 var isHover= false ; //判断是否悬浮在上方 var preOvTime= new Date().getTime(); //上次悬浮时间 function over(e){ var curOvTime= new Date().getTime(); isHover= true ; //处于over状态 if (curOvTime-preOvTime>10) { //时间间隔超过10毫秒,认为鼠标完成了mouseout事件 overCallback(e,elem); } preOvTime=curOvTime; } function out(e) { var curOvTime= new Date().getTime(); preOvTime=curOvTime; isHover= false ; setTimeout( function (){ if (!isHover) { outCallback(e,elem); } },10); } bind(elem, "mouseover" ,over); bind(elem, "mouseout" ,out); }; hover(document.getElementById( "dd" ), function (){console.log( "进来1" ); document.getElementById( "dd2" ).innerHTML= "进来了" ;}, function (){ console.log( "出来2" ); document.getElementById( "dd2" ).innerHTML= "出来了" ; } ); </script> </body> </html> |
1 2 3 4 5 | jQuery.fn.extend( { hover: function ( fnOver, fnOut ) { return this .mouseenter( fnOver ).mouseleave( fnOut || fnOver ); } } ); |
获取文档高度
1 2 3 4 5 6 7 | //获取文档完整的高度 var getScrollHeight= function () { return Math.max(document.body.scrollHeight, document.documentElement.scrollHeight); } console.log( 'jquery文档高度' +jQuery(document).height()); //jquery文档高度1739 console.log( 'js文档高度' +getScrollHeight()); // js文档高度1739g滚动条 |
滚动条高度
1 2 3 4 5 6 7 | document.getElementById("element").addEventListener("click",function(){ var scrollTop1 = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop; var scrollTop2 = window.scrollY||document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop; console.log('scrollTop1'+scrollTop1) console.log('scrollTop2'+scrollTop2) }); |
样式操作
// jQuery $('.el').addClass('class'); $('.el').removeClass('class'); $('.el').toggleClass('class'); // 原生方法 document.querySelector('.el').classList.add('class'); document.querySelector('.el').classList.remove('class'); document.querySelector('.el').classList.toggle('class'); // 原生方法 扩展添加多个 DOMTokenList.prototype.adds = function(tokens) { tokens.split(" ").forEach(function(token) { this.add(token); }.bind(this)); return this; }; // adds 添加多个 document.querySelector(".el").classList.adds("child1 child2 child3");
function hasClass(ele, cls) { return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')); } function addClass(ele, cls) { if (!this.hasClass(ele, cls)) ele.className += " " + cls; } function removeClass(ele, cls) { if (hasClass(ele, cls)) { var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)'); ele.className = ele.className.replace(reg, ' '); } }
获取jsonp
function getJSONP2(url,success,jsonpCallback,jsonp){ var jsonp=jsonp||"callback", cn=jsonpCallback||"jsonpCallback", url=url.toString(), dataString = url.indexOf('?') == -1? '?': '&', s=document.createElement("script"), head=document.head||document.getElementsByTagName("head")[0]; s.type="text/javascript"; s.charset="UTF-8";s.src=url+dataString+"_="+(+new Date)+"&"+jsonp+"="+cn; head.insertBefore(s,head.firstChild); console.log("src",s.src); setTimeout(function(){ window[cn]=function(data){ try{s.onload=s.onreadystatechange=function(){ var that=this; if((!that.readyState||that.readyState==="loaded"||that.readyState==="complete")){ success&&success(data); s.onload=s.onreadystatechange=null;if(head&&s.parentNode){ head.removeChild(s)}}}}catch(e){}finally{window[cn]=null}} },0)};
var url44="http://api.map.baidu.com/geocoder/v2/?sa=1&location=30.290466116991468,120.00192773949404&output=json&pois=1&latest_admin=1&ak=ABq5yEuwLp5Z4yWlRDGX3vEhxxjGDu8L"; getJSONP2(url44,function(data){ var data=data; data.regeocode=data.result; //var address = data.regeocode.formatted_address; console.log(data,"结果" , data.regeocode.formatted_address); })
1 2 3 4 5 6 | //document.addEventListener('click',function(){ getJSONP( "https://api.github.com/repos/HubSpot/pace?callback=" , function (json){ alert( 'success!' + json.data.id+ '获取到的' +json.data.name); document.getElementById( "testText" ).innerHTML= '回调函数获取到了' +json.data.name; document.getElementById( "testText" ).style.cssText= 'color:red;font-size:22px; border:1px solid #666' }); |
清楚字符串空格
function trimStr(str){return str.replace(/(^\s*)|(\s*$)/g,"");} function TrimAll(str,is_global){ //删除全部空格 var result; result = str.replace(/(^\s+)|(\s+$)/g,""); if(is_global.toLowerCase()=="g") { result = result.replace(/\s/g,""); } return result; }
1 2 3 4 5 6 7 8 9 10 11 12 13 | tring.prototype.trim = function () { return this .replace(/(^\s*)|(\s*$)/g, "" ); }; String.prototype.ltrim = function () { return this .replace(/(^\s*)/g, "" ); }; String.prototype.rtrim = function () { return this .replace(/(\s*$)/g, "" ); }; String.prototype.trimAll = function () { return this .replace(/\s+/g, "" ); } |
cookie的操作
function addCookie(objName,objValue,objHours){ var str = objName + "=" + escape(objValue); if(objHours > 0){ var date = new Date(); var ms = objHours*3600*1000; date.setTime(date.getTime() + ms); str += "; expires=" + date.toGMTString(); } str += "; path=/"; document.cookie = str; }; function getCookie (objName){ var arrStr = document.cookie.split("; "); for(var i = 0;i < arrStr.length;i ++){ var temp = arrStr[i].split("="); if(temp[0] == objName) return unescape(temp[1]); } };
原生ajax的操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /** * ajax封装 * var xmlhttp = new YAjax(); * xmlhttp.request({ * url : "./demo.php", // get请求时 可以这样写 "./demo.php?name=zhangsan" * method : "POST", * data : "name=李四", // 支持json传值 {"name":"zhangsan"} get时不用该参数 * receiveType : "html", // json html or xml * timeout : 3000, // 3秒 async : true, //默认true 可省略 * beforeSend:function(){}, //请求之前回调函数 就得 这边beforesent s小写 beforesend * success : function(d) {alert(d);}, * error : function(xmlhttp){alert('timeout');} * }); */ |
function YAjax() { this._self = this; this.xmlhttp = this.init() } YAjax.prototype = { constructor: YAjax, init: function() { var xmlhttp = null; if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); if (xmlhttp.overrideMimeType) { xmlhttp.overrideMimeType("text/xml") } } else { if (window.ActiveXObject) { var activexName = ["MSXML2.XMLHTTP", "Microsoft.XMLHTTP"]; for (var i = 0; i < activexName.length; i++) { try { xmlhttp = new ActiveXObject(activexName[i]); break } catch(e) {} } } } return xmlhttp }, extend: function(destination, source, override) { if (undefined == override) { override = true } if (typeof destination != "object" && typeof destination != "function") { if (!override) { return destination } else { destination = {} } } var property = ""; for (property in source) { if (override || !(property in destination)) { destination[property] = source[property] } } return destination }, json2String: function(jsonData) { var strArr = []; for (var k in jsonData) { strArr.push(k + "=" + jsonData[k]) } return strArr.join("&") }, request: function(opt) { var _self = this, isTimeout = false, timeFlag = 0, options = { url: "", data: "", method: "POST", receiveType: "html", timeout: 7000, async: opt.async || true, beforeSend: function() {}, success: function() { alert("define your success function") }, error: function(xmlhttp) {} }; if ("data" in opt) { if (typeof opt.data == "string") {} else { opt.data = this.json2String(opt.data) } } options = this.extend(options, opt); this.xmlhttp.onreadystatechange = function() { if (_self.xmlhttp.readyState == 2) { options.beforeSend && options.beforeSend.apply(_self.xmlhttp, arguments) } if (_self.xmlhttp.readyState == 4) { if (!isTimeout && _self.xmlhttp.status == 200) { clearTimeout(timeFlag); var t = options.receiveType.toLowerCase(); if (t == "html") { options.success(_self.xmlhttp.responseText) } else { if (t == "xml") { options.success(_self.xmlhttp.responseXML) } else { if (t == "json") { try { var obj = JSON.parse(_self.xmlhttp.responseText); options.success(obj) } catch(e) { var str = "(" + _self.xmlhttp.responseText + ")"; options.success(JSON.parse(str)) } } else {} } } } else { clearTimeout(timeFlag); options.error(_self.xmlhttp) } } }; clearTimeout(timeFlag); timeFlag = setTimeout(function() { if (_self.xmlhttp.readyState != 4) { isTimeout = true; _self.xmlhttp.abort(); clearTimeout(timeFlag) } }, options.timeout); this.xmlhttp.open(options.method.toUpperCase(), options.url, options.async); if (options.method.toUpperCase() == "POST") { this.xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); this.xmlhttp.send(options.data) } else { this.xmlhttp.send(null) } } };
原生延迟加载插件

/*! echo.js v1.7.0 | (c) 2015 @toddmotto | https://github.com/toddmotto/echo */ (function (root, factory) { if (typeof define === 'function' && define.amd) { define(function() { return factory(root); }); } else if (typeof exports === 'object') { module.exports = factory; } else { root.echo = factory(root); } })(this, function (root) { 'use strict'; var echo = {}; var callback = function () {}; var offset, poll, delay, useDebounce, unload,effectClass; var classList= 'classList' in document.documentElement ?1:0; var isHidden = function (element) { return (element.offsetParent === null); }; var inView = function (element, view) { if (isHidden(element)) { return false; } var box = element.getBoundingClientRect(); return (box.right >= view.l && box.bottom >= view.t && box.left <= view.r && box.top <= view.b); }; var debounceOrThrottle = function () { if(!useDebounce && !!poll) { return; } clearTimeout(poll); poll = setTimeout(function(){ echo.render(); poll = null; }, delay); }; echo.init = function (opts) { opts = opts || {}; var offsetAll = opts.offset || 0; var offsetVertical = opts.offsetVertical || offsetAll; var offsetHorizontal = opts.offsetHorizontal || offsetAll; var optionToInt = function (opt, fallback) { return parseInt(opt || fallback, 10); }; offset = { t: optionToInt(opts.offsetTop, offsetVertical), b: optionToInt(opts.offsetBottom, offsetVertical), l: optionToInt(opts.offsetLeft, offsetHorizontal), r: optionToInt(opts.offsetRight, offsetHorizontal) }; delay = optionToInt(opts.throttle, 80); useDebounce = opts.debounce !== false; effectClass=opts.effectClass; unload = !!opts.unload; callback = opts.callback || callback; echo.render(); if (document.addEventListener) { root.addEventListener('scroll', debounceOrThrottle, false); root.addEventListener('load', debounceOrThrottle, false); } else { root.attachEvent('onscroll', debounceOrThrottle); root.attachEvent('onload', debounceOrThrottle); } }; echo.render = function () { var nodes = document.querySelectorAll('img[data-echo], [data-echo-background]'); var length = nodes.length; var src, elem; var view = { l: 0 - offset.l, t: 0 - offset.t, b: (root.innerHeight || document.documentElement.clientHeight) + offset.b, r: (root.innerWidth || document.documentElement.clientWidth) + offset.r }; for (var i = 0; i < length; i++) { elem = nodes[i]; if (inView(elem, view)) { if (unload) { elem.setAttribute('data-echo-placeholder', elem.src); } if (elem.getAttribute('data-echo-background') !== null) { elem.style.backgroundImage = "url(" + elem.getAttribute('data-echo-background') + ")"; } else { elem.src = elem.getAttribute('data-echo'); } if (!unload) { if(effectClass){ if (classList){ elem.classList.add(effectClass); }else{ elem.className += " " + effectClass; } } elem.removeAttribute('data-echo'); elem.removeAttribute('data-echo-background'); } callback(elem, 'load'); } else if (unload && !!(src = elem.getAttribute('data-echo-placeholder'))) { if (elem.getAttribute('data-echo-background') !== null) { elem.style.backgroundImage = "url(" + src + ")"; } else { elem.src = src; } elem.removeAttribute('data-echo-placeholder'); callback(elem, 'unload'); } } if (!length) { echo.detach(); } }; echo.detach = function () { if (document.removeEventListener) { root.removeEventListener('scroll', debounceOrThrottle); } else { root.detachEvent('onscroll', debounceOrThrottle); } clearTimeout(poll); }; return echo; });
使用方法
<img src="img/blank.gif" alt="Photo" data-echo="img/photo.jpg"> <script src="../echo.js"></script> <script> echo.init({ offset: 100, throttle: 250, unload: false, callback: function (element, op) { console.log(element, 'has been', op + 'ed') } });
domready(fn)

function Domready(readyFn) { if (document.addEventListener) { document.addEventListener("DOMContentLoaded", function() { readyFn && readyFn() }, false) } else { var bReady = false; document.attachEvent("onreadystatechange", function() { if (bReady) { return } if (document.readyState == "complete" || document.readyState == "interactive") { bReady = true; readyFn && readyFn() } }); setTimeout(checkDoScroll, 1) } function checkDoScroll() { try { document.documentElement.doScroll("left"); if (bReady) { return } bReady = true; readyFn && readyFn() } catch (e) { setTimeout(checkDoScroll, 1) } } };
为元素添加on方法
Element.prototype.on = Element.prototype.addEventListener;
为元素添加trigger方法
1 2 3 4 5 6 7 8 9 | HTMLElement.prototype.trigger = function (type, data) { var event = document.createEvent( 'HTMLEvents' ); event.initEvent(type, true , true ); event.data = data || {}; event.eventName = type; event.target = this ; this .dispatchEvent(event); return this ; }; |
获取文档完整的高度
1 2 3 4 | //获取文档完整的高度 var getScrollHeight= function () { return Math.max(document.body.scrollHeight, document.documentElement.scrollHeight); } |
获取当前可是范围的高度
1 2 3 4 5 6 7 8 9 10 11 | //获取当前可是范围的高度 var getClientHeight= function () { var clientHeight = 0; if (document.body.clientHeight && document.documentElement.clientHeight) { clientHeight = Math.min(document.body.clientHeight, document.documentElement.clientHeight); } else { clientHeight = Math.max(document.body.clientHeight, document.documentElement.clientHeight); } return clientHeight; } |
getScrollParent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | function getScrollParent(element, includeHidden, documentObj) { let style = getComputedStyle(element); const excludeStaticParent = style.position === 'absolute'; const overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/; if (style.position === 'fixed') { return documentObj.body; } let parent = element.parentElement; while (parent) { style = getComputedStyle(parent); if (excludeStaticParent && style.position === 'static') { continue; } if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) { return parent; } parent = parent.parentElement; } return documentObj.body; } |
其他
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 'use strict'; module.exports = (object, onChange) => { const handler = { get(target, property, receiver) { try { return new Proxy(target[property], handler); } catch (err) { return Reflect.get(target, property, receiver); } }, defineProperty(target, property, descriptor) { onChange(); return Reflect.defineProperty(target, property, descriptor); }, deleteProperty(target, property) { onChange(); return Reflect.deleteProperty(target, property); } }; return new Proxy(object, handler); }; |
数组
Object.assign
/** * The Object.assign() method is used to copy the values of all enumerable own properties from one or more source * objects to a target object. It will return the target object. * This polyfill doesn't support symbol properties, since ES5 doesn't have symbols anyway * Source: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign * @function * @ignore */ if (!Object.assign) { Object.defineProperty(Object, 'assign', { enumerable: false, configurable: true, writable: true, value: function(target) { if (target === undefined || target === null) { throw new TypeError('Cannot convert first argument to object'); } var to = Object(target); for (var i = 1; i < arguments.length; i++) { var nextSource = arguments[i]; if (nextSource === undefined || nextSource === null) { continue; } nextSource = Object(nextSource); var keysArray = Object.keys(nextSource); for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { var nextKey = keysArray[nextIndex]; var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); if (desc !== undefined && desc.enumerable) { to[nextKey] = nextSource[nextKey]; } } } return to; } }); }
/**
* Get bounding client rect of given element
* @function
* @ignore
* @param {HTMLElement} element
* @return {Object} client rect
*/
function getBoundingClientRect(element) {
var rect = element.getBoundingClientRect();
// whether the IE version is lower than 11
var isIE = navigator.userAgent.indexOf("MSIE") != -1;
// fix ie document bounding top always 0 bug
var rectTop = isIE && element.tagName === 'HTML'
? -element.scrollTop
: rect.top;
return {
left: rect.left,
top: rectTop,
right: rect.right,
bottom: rect.bottom,
width: rect.right - rect.left,
height: rect.bottom - rectTop
};
}
。。。。剩下的慢慢添加...
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话