多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > web前端 > jscript > 使用clickCatcher在JS文件加載完畢/事件應用之前捕獲Click事件

使用clickCatcher在JS文件加載完畢/事件應用之前捕獲Click事件

來源:程序員人生   發布時間:2013-12-12 13:18:26 閱讀次數:2979次

提高網站性能的方法之一就是將JavaScript文件放到文檔的底部(我在Improve Your Web Site Performance – Tips & Tricks To Get A Good YSlow Rating中討論過)。但是,這有一個缺點。

問題

在JavaScript文件加載完畢運行之前,你打算為文檔中一些元素分配一個事件處理器。如果用戶此時單擊這些元素,會發生什么情況?那么瀏覽器將執行元素默認的行為。如,一個將用戶帶到另外一個頁面的鏈接,而你并不打算這么做,而是想通過AJAX或其他方式動態加載一些信息。

理論解決方案

最近,我和我的同事David Billskog討論并研究了這個問題,其解決方案是在文檔的頭部包含一個JavaScript塊(inline或included),并確信能捕獲頁面中所有的click事件。然后過濾它們確定一個元素正是你正打算應用事件處理器的那個元素。

最后,當頁面加載完畢/事件處理器已經分配時,移除先前分配的clickCatcher,迭代在這之前被點擊的所有元素,然后觸發這些元素真正的click事件,引發正常的和應用的事件行為。

實際解決方案

我和David開始各自的工作,對我來說,解決方案不需要任何JavaScript庫,而David的解決方案是基于jQuery版本的(可以很容易的應用到任何其它庫中)。我列出我的解決方案——clickCatcher。

clickCatcher使用一些簡單的script函數作為基礎:

  • addEvent——在不覆蓋任何可能被分配click事件處理器的情況下,為文檔分配一個click事件。
  • removeEvent——一旦頁面加載完畢,移除上面分配的事件,并不再繼續捕獲clilck事件。
  • fireEvent——在JavaScript文件已加載完畢之前,釋放被單擊的所有元素的click事件。

The clickCatcher

(function () {	clickCatcher = function () {		var clicks = [],			addClicks = function (evt) {				var classCheck = /catch/,					body = /body/i,					target = (evt.target)? evt.target : evt.srcElement;				while (!classCheck.test(target.className) && !body.test(target.nodeName)) {					target = target.parentNode;				}				if (classCheck.test(target.className)) {					clicks.push(target);					if (evt.preventDefault) {						evt.preventDefault();					}					evt.returnValue = false;					return false;				}			},			callClicks = function () {				removeEvent(document, "click", addClicks);				for (var i=0, il=clicks.length; i<il; i++) {					fireEvent(clicks[i], "click");				};			},			init = function () {				addEvent(document, "click", addClicks);				// Could be called here, but now called manually in script loaded later - adapt to your situation				//addEvent(window, "load", callClicks);			};		return {			init : init,			callClicks : callClicks		};	}();	clickCatcher.init();	return clickCatcher;})();

clickCatcher封裝在一個匿名的自調用函數之中,這樣就不會與網頁的全局變量相混淆,而是創建自己的作用域。如果你想在其它地方訪問它,這部分代碼可以選擇性的暴露clickCatcher對象自身。代碼給文檔附加一個事件處理器,如果被單擊的元素(或任何它的父元素)有類名catch(如鏈接),就將每一個click存儲到一個數組中。

一旦頁面加載完畢,你可以讓其自動調用,或你可以通過調用clickCatcher.callClicks()方法手動觸發它;

包含addEvent, removeEvent, fireEvent方法完整的代碼,看起來就是這樣:

// By Robert Nyman, http://robertnyman.com/clickcatcher/ - This content is released under the MIT License: http://www.opensource.org/licenses/mit-license.php(function () {	// addEvent by John Resig, http://ejohn.org/blog/flexible-javascript-events/	function addEvent( obj, type, fn ) {		if ( obj.attachEvent ) {			obj['e'+type+fn] = fn;			obj[type+fn] = function(){obj['e'+type+fn]( window.event );}			obj.attachEvent( 'on'+type, obj[type+fn] );		} else			obj.addEventListener( type, fn, false );	}	function removeEvent( obj, type, fn ) {		if ( obj.detachEvent ) {			obj.detachEvent( 'on'+type, obj[type+fn] );			obj[type+fn] = null;		} else			obj.removeEventListener( type, fn, false );	}	// fireEvent by Jehiah Czebotar, http://jehiah.cz/archive/firing-javascript-events-properly	function fireEvent(element, event) {		var evt;		if (document.createEvent) {			// dispatch for firefox + others			evt = document.createEvent("HTMLEvents");			evt.initEvent(event, true, true ); // event type,bubbling,cancelable			return !element.dispatchEvent(evt);		} else {		// dispatch for IE			evt = document.createEventObject();			return element.fireEvent('on'+event,evt);		}	}	clickCatcher = function () {		var clicks = [],			addClicks = function (evt) {				var classCheck = /catch/,					body = /body/i,					target = (evt.target)? evt.target : evt.srcElement;				while (!classCheck.test(target.className) && !body.test(target.nodeName)) {					target = target.parentNode;				}				if (classCheck.test(target.className)) {					clicks.push(target);					if (evt.preventDefault) {						evt.preventDefault();					}					evt.returnValue = false;					return false;				}			},			callClicks = function () {				removeEvent(document, "click", addClicks);				for (var i=0, il=clicks.length; i<il; i++) {					fireEvent(clicks[i], "click");				};			},			init = function () {				addEvent(document, "click", addClicks);				// Could be called here, but now called manually in script loaded later - adapt to your situation				//addEvent(window, "load", callClicks);			};		return {			init : init,			callClicks : callClicks		};	}();	clickCatcher.init();	return clickCatcher;})();

你可以到clickCatcher頁測試這些代碼。

setTimeout 技巧

但是,不管是是從clickCatcher內部來觸發clicks的執行,還是手動調用它們,你要確信這是最后調用的。David研究中的一個有趣的結果是,你可以通過使用setTimeout控制調用棧,time設置為0,這樣,相對于其它完全相同load事件處理器,它將被放置到棧的最后。

也將就是說,如果你在window已加載時使用addEvent調用某些東西,你可以像這樣控制它(或許只在同一個script塊或JavaScript文件中時相對安全)。

// Calling click handlersetTimeout(function () {	addEvent(window, "load", callClicks);}, 0);// My own function - will be called before the above functionaddEvent(window, "load", myCoolFunc);

jQuery 版本

先前我提到過David的jQuery版本,這意味著在你調用之前須包含jQuery,但是你可以將其它JavaScript文件放到頁面底部。他介紹了他的方法,結果在clickCatcher with jQuery 。

反饋?

從我們的測試中看到,在JavaScript加載完畢之前捕獲click事件,這是一個有效可靠的方法。你仍可以在文檔的底部放置js來提升網站性能。

原文地址:http://robertnyman.com/2010/05/24/catching-clicks-with-clickcatcher-before-your-javascript-files-have-loadedevents-been-applied/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+robertnyman+%28Robert%27s+talk%29

轉載地址:http://www.denisdeng.com/?p=1018

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 免费欧洲毛片a级视频 | 亚洲欧美日韩精品久久亚洲区 | 国产精品国产三级国产专区不 | 美女牲交视频一级毛片 | 亚洲国产成人久久精品图片 | 视频在线免费 | 日本 免费 高清 | 免费黄网址 | 性欧美激情videos | 亚洲国产成人资源在线软件 | 亚洲精品一区二区 | 亚洲天堂网在线播放 | 亚洲清色 | 国内精品久久久久影院中国 | 自拍偷拍第4页 | 18男女很黄的视频 | 国产亚洲欧美成人久久片 | 欧美午夜精品久久久久免费视 | 激情欧美一区二区三区 | 最近最新中文字幕国语片 | 欧美h视频在线观看 | 男女视频免费 | 欧美刺激性色黄大片18 | www视频在线观看天堂 | 久久片| xart欧美在线播放精品4k | 99热精品成人免费观看 | 日本一区二区三区免费高清在线 | 91国色| 欧美日韩亚洲国产精品一区二区 | 四虎在线永久精品高清 | 国产粉嫩00福利福利福利 | 精品亚洲77777www | 精品国产福利片在线观看 | 在线视频精品视频 | 日产一区二区三区四区 | 日本福利片秋霞国产午夜 | 性色aⅴ闺蜜一区二区三区 性色aⅴ在线观看swag | 福利片一区 | 国产69精品久久久久9999 | 九色九色九色在线综合888 |