用原生javascript實現jQuery效果——自訂javascript擴充DOM函數及功能

來源:互聯網
上載者:User

     幾天前參考了一本關於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.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)//用於判斷非IEeval("HTMLElement.prototype."+name+"=fn");else{//IEvar _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);}elsereturn 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);}elsethrow 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()方法達到需要的效果。
 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.