用原生javascript实现jQuery效果——自定义javascript扩展DOM函数及功能

     几天前参考了一本关于jQuery的国内的书,学习了如何用原生的javascript实现jQuery的"功能"——自定义函数扩展DOM功能,来仿制部分的jQuery效果。因为发现这样的方法可以在无法使用jQuery的时候(例如和其他框架及自定义函数发生冲突)对想要的效果直接构造实现(只为一小部分功能)。这里主要是关注构造和实现的过程。

    首先来看事情的起因: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.οnlοad=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[n]){
		return _this.style[n];
	}
	else if(_this.currentStyle){
		return _this.currentStyle[n];
	}
	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" οnclick="bonce()"/>
       </div>
       <div id="loginsub">
           <div id="hiddenlog" style="display:none;">
                <!--被隐藏的部分-->
           </div> 
       </div>    
    </div>
   <!--login end-->

 

由此我得以在不使用jQuery的条件下构造出slideDown()方法达到需要的效果。
 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值