用原生javascript实现jQuery效果——自定义javascript扩展DOM函数及功能
2012-12-13 13:18
1136 查看
几天前参考了一本关于jQuery的国内的书,学习了如何用原生的javascript实现jQuery的"功能"——自定义函数扩展DOM功能,来仿制部分的jQuery效果。因为发现这样的方法可以在无法使用jQuery的时候(例如和其他框架及自定义函数发生冲突)对想要的效果直接构造实现(只为一小部分功能)。这里主要是关注构造和实现的过程。
首先来看事情的起因:n天前,在一个自己东拼西凑(主要是拼凑了两个别人的首页幻灯图片切换js)帮别人做的一个页面上,试图用jQuery增加一些动态更美观,于是对某个用于登录的表单窗口进行隐藏,并打算用slideDown()进行动态弹出出控制。在脚本没有任何错误的情况下,发现无论如何没有效果。在firefox中打开web控制台,调用动作没有响应,感觉$初始化未起作用,于是更换为函数方法调用,出现这样的报错:
$(...).is is not a function
不得其解,后来逐一排除,发现当我删掉其他几个js的脚本调用时,恢复了正常。最后把问题确认在了一个名为ntes_jslib_1.x.js的脚本上:
这是一个网上找来到滑动切换的脚本,未打开细看。发现把此脚本去除就恢复正常。由此确定是jQuery与它发生的冲突。于是思考解决办法。down来的脚本没有细看,更换其他框架又不求甚解(虽然本来也没有去刨根问底)。于是想到用原生方法能否实现(仅仅为了一个小动态,不再使用jQuery)。这便回忆起之前在一本书上对扩展DOM的了解(书名为《犀利开发jQuery内核详解与实践》,作者:朱印宏)。于是找回书本进行尝试。
对于扩展DOM函数功能来说,DOM与javascript具有不同的“作用域”,由书上的例子来说,下面的功能是无法实现的:
因此,扩展DOM的必要就在于在使用javascript扩展功能之前,为其提供作用的基础。
对于DOM的扩展,因为浏览器的两大派别(其实还是因为神IE的不支持HTMLElement类型),有两种需要:对HTMLElement类型原型对象添加自定义方法(IE不支持),和对DOM节点绑定自定义方法(for IE)。
详细的实现如下:
由此之后,在构造了DOMextend()方法的基础上,就可以继续扩展和构造其他的自定义函数:
我想要模仿的,是jQuery的slideDown()功能,因此我需要先构造的方法有:
getStyle()用于获取元素样式,offset()用于获取绝对偏移位置,fromStyle()用于将样式值转换为数值进行运算,setCSS()用于设置元素样式,resetCSS()用于设置样式之后恢复样式,以及width()和height()用于获取元素的宽和高。
详细如下:
最后,万事俱备,构造slideDown():
在我需要调用的部分进行调用:
js部分:
页面部分:
由此我得以在不使用jQuery的条件下构造出slideDown()方法达到需要的效果。
首先来看事情的起因:n天前,在一个自己东拼西凑(主要是拼凑了两个别人的首页幻灯图片切换js)帮别人做的一个页面上,试图用jQuery增加一些动态更美观,于是对某个用于登录的表单窗口进行隐藏,并打算用slideDown()进行动态弹出出控制。在脚本没有任何错误的情况下,发现无论如何没有效果。在firefox中打开web控制台,调用动作没有响应,感觉$初始化未起作用,于是更换为函数方法调用,出现这样的报错:
$(...).is is not a function
不得其解,后来逐一排除,发现当我删掉其他几个js的脚本调用时,恢复了正常。最后把问题确认在了一个名为ntes_jslib_1.x.js的脚本上:
<script language="javascript" src="js/ntes_jslib_1.x.js" type="text/javascript" charset=utf-8></script>
这是一个网上找来到滑动切换的脚本,未打开细看。发现把此脚本去除就恢复正常。由此确定是jQuery与它发生的冲突。于是思考解决办法。down来的脚本没有细看,更换其他框架又不求甚解(虽然本来也没有去刨根问底)。于是想到用原生方法能否实现(仅仅为了一个小动态,不再使用jQuery)。这便回忆起之前在一本书上对扩展DOM的了解(书名为《犀利开发jQuery内核详解与实践》,作者:朱印宏)。于是找回书本进行尝试。
对于扩展DOM函数功能来说,DOM与javascript具有不同的“作用域”,由书上的例子来说,下面的功能是无法实现的:
var appendTo()=function(e){ e.appendChild(this); return this; } window.onload=function(){ var div=document.getElementsByTagName("div")[0]; var h1=document.createElement("h1"); h1.appendTo(div);//调用自定义的方法,实际无法实现 }
因此,扩展DOM的必要就在于在使用javascript扩展功能之前,为其提供作用的基础。
对于DOM的扩展,因为浏览器的两大派别(其实还是因为神IE的不支持HTMLElement类型),有两种需要:对HTMLElement类型原型对象添加自定义方法(IE不支持),和对DOM节点绑定自定义方法(for IE)。
详细的实现如下:
var DOMextend=function(name,fn){ if(!document.all)//用于判断非IE eval("HTMLElement.prototype."+name+"=fn"); else{//IE var _createElement=document.createElement;//存储原方法 document.createElement=function(tag){//重写方法,为createElement()绑定自定义 var _elem=_createElement(tag);//首先加入原方法 eval("_elem."+name+"=fn");//绑定自定义,下同 return _elem; } var _getElementById=document.getElementById; document.getElementById=function(id){//为getElementById()绑定自定义 var _elem=_getElementById(id); eval("_elem."+name+"=fn"); return _elem; } var _getElementsByTagName=document.getElementsByTagName; document.getElementsByTagName=function(tag){//为getElementsByTagName()绑定自定义 var _arr=_getElementsByTagName(tag); for(var _elem=0;_elem<_arr.length;_elem++) eval("_arr[_elem]."+name+"=fn"); return _arr; } } };
由此之后,在构造了DOMextend()方法的基础上,就可以继续扩展和构造其他的自定义函数:
我想要模仿的,是jQuery的slideDown()功能,因此我需要先构造的方法有:
getStyle()用于获取元素样式,offset()用于获取绝对偏移位置,fromStyle()用于将样式值转换为数值进行运算,setCSS()用于设置元素样式,resetCSS()用于设置样式之后恢复样式,以及width()和height()用于获取元素的宽和高。
详细如下:
DOMextend("getStyle",function(n){ var _this=this; if(_this.style ){ return _this.style ; } else if(_this.currentStyle){ return _this.currentStyle ; } else if(document.defaultView && document.defaultView.getComputedStyle) { n=n.replace(/([A-Z])/g,"-$1"); n=n.toLowerCase(); var s=document.defaultView.getComputedStyle(_this,null); if(s) return s.getPropertyValue(n); } else return null; }) DOMextend("offset",function(){ var _this=this; var left=0,top=0; while(_this.offsetParent){ left+=_this.offsetLeft; top+=_this.offsetTop; _this=_this.offsetParent; } return{ "left":left, "top":top }; }) DOMextend("fromStyle",function(w,p){ var _this=this; var p=arguments[2]; if(!p) p=1; if(/px/.test(w) && parseInt(w)) return parseInt(parseInt(w)*p); else if(/\%/.tese(w)&&parseInt(w)){ var b=parseInt(w)/100; if((p!=1)&&p) b*=p; _this=_this.parentNode; if(_this.tagName=="BODY") throw new Error("无尺寸!"); w=_this.getStyle("width");//方法之间很多穿插使用 return arguments.callee(_this,w,b); } else if(/auto/.test(w)){ var b=1; if((p!=1)&&p) b*=p; _this=_this.parentNode; if(_this.tagName=="BODY") throw new Error("无尺寸!"); w=_this.getStyle("width"); return arguments.callee(_this,w,b); } else throw new Error("特殊单位!"); }) DOMextend("setCSS",function(o){ var _this=this; var a={}; for(var i in o){ a[i]=_this.style[i]; _this.style[i]=o[i]; } return a; }) DOMextend("resetCSS",function(o){ var _this=this; for(var i in o){ _this.style[i]=o[i]; } }) DOMextend("width",function(){ var _this=this; if(_this.getStyle("display")!="none") return _this.offsetWidth||_this.fromStyle(_this.getStyle("width")); var r=_this.setCSS({ display:"", position:"absolute", visibility:"hidden" }); var w=_this.offsetWidth ||_this.fromStyle(_this.getStyle("width")); _this.resetCSS(r); return w; }) DOMextend("height",function(){ var _this=this; if(_this.getStyle("display")!="none") return _this.offsetHeight||_this.fromStyle(_this.getStyle("height")); var r=_this.setCSS({ display:"", position:"absolute", visibility:"hidden" }); var h=_this.offsetHeight ||_this.fromStyle(_this.getStyle("height")); _this.resetCSS(r); return h; })
最后,万事俱备,构造slideDown():
DOMextend("slideDown",function(time,fn){ var _this=this; var isShow=_this.getStyle("display"); if(isShow!="none") return; var oldcss=_this.setCSS({ display:"", visibility:"hidden" }) var x=_this.offset().left; var y=_this.offset().top; var height=_this.height(); var width=_this.width(); _this.resetCSS(oldcss); _this.style.display=""; var box=_this.cloneNode(true); for(var i=0;i<box.childNodes.length;i++){ box.removeChild(box.childNodes[i]); } _this.parentNode.insertBefore(box,_this); _this=_this.parentNode.removeChild(_this); box.appendChild(_this); box.style.overflow="hidden"; box.style.display=""; box.style.height=0; box.style.width=width; var step=5; var stepheight=step*height/time; var curstep=0; var interval=setInterval(function(){ if(curstep>=height){ clearInterval(interval); _this=_this.parentNode.removeChild(_this); box.parentNode.insertBefore(_this,box); box.parentNode.removeChild(box); fn(); } else{ curstep+=stepheight; box.style.height=curstep+"px"; } },step); })
在我需要调用的部分进行调用:
js部分:
function bonce(){ var hiddes=document.getElementById("hiddenlog"); hiddes.slideDown(300,function(){;}//暂不需要回调函数,空语句 );}
页面部分:
<!----login start--> <div id="login"> <div id="loginmen"> <img src="images/glydl.png" id="loginbonce" onclick="bonce()"/> </div> <div id="loginsub"> <div id="hiddenlog" style="display:none;"> <!--被隐藏的部分--> </div> </div> </div> <!--login end-->
由此我得以在不使用jQuery的条件下构造出slideDown()方法达到需要的效果。
相关文章推荐
- 不用JQuery,原生Javascript实现Ajax功能及相关知识点
- 使用原生JS实现jQuery的addClass, removeClass, hasClass函数功能
- 使用JQuery库提供的扩展功能实现自定义方法
- 陈华:jquery不转原生javascript实现热点无缝滚动效果代码复用
- 详解用原生JavaScript实现jQuery的某些简单功能
- Dom利用javascript实现模拟弹出对话框效果的代码,类似JQuery中的dialog!
- 原生JavaScript实现jsindexOf()函数功能
- 原生JavaScript与jQuery(绝对、相对定位)实现拖拽效果
- 不用JQuery,原生Javascript实现Ajax功能及相关知识点
- jQuery插件Datepicker日期选择器实现Javascript自定义日期时间选择功能
- 原生javascript实现分页效果+搜索功能
- 原生javascript 实现jQuery代码效果对比
- 使用JQuery库提供的扩展功能实现自定义方法
- 不用JQuery,原生Javascript实现Ajax功能及相关知识点
- jQuery学习之路(7)- 用原生JavaScript实现jQuery的某些简单功能
- 使用原生JS实现jQuery的addClass, removeClass, hasClass函数功能
- jQuery的index()原生js实现以及删除空白文本节点函数
- JS自定义功能函数实现动态添加网址参数修改网址参数值
- 原生js实现jQuery的功能 height()方法实现(一)
- 纯原生javascript实现图片轮播切换效果代码。