关闭

我自作聪明,擅自主张的优化了jQuery选择器。

标签: JavaScriptjs缓存系统jquery优化
423人阅读 评论(1) 收藏 举报
分类:
</pre><pre name="code" class="javascript">闲了一会,写篇博客。
最近项目里面,我自作聪明,擅自主张的,自我感觉的优化了一下jQuery选择器。哈哈哈~~~~ ( ﹁ ﹁ )

我这么想的:

jQuery最底层采用getById getByTagName,2.0版本之后结合最近html5的API--getByClassName。
如果没有getByClassName.将进行所搜查找className选择器。
滥用jQuery,诸如:

$('.TestClassName')

它将从全局元素搜索复合className包含TestClassName的元素返回。

所以 
$('.TestClassName') 
不如写成更为精确的选择符,比如:
$('div.TestClassName')
$('#someId div.TestClassName')
这样将缩减搜索范围。

可以尝试将操作元素缓存起来,这样更有利。
比如:
var $TestClassName = $('#someId div.TestClassName');
这样就可以重复利用$TestClassName,效果感觉还不错
虽然如此,每次还要去找$TestClassName变量名防止忘记和写错,有时不知道是否定义过这个变量,而且想变量名也是件痛苦的事情。
所以很麻烦。

我们尝试开发一个缓存系统。比如命名一个变量空间或者构造函数之类的来初始化和存储这些操作元素缓存。
var DomCache = function(){
	this._cache = {};
}
// 获取元素节点
DomCache.prototype.getNode = function(tag){
	return this._cache[tag];
}
// 设置元素节点
DomCache.prototype.setNode = function(tag, _$){
	this._cache[tag] = _$
}
// 所有需要操作的元素标识符
var All_Init_Selectors = "#id1|#id2|#id3|.class1|.class2|.class3";

// 初始化缓存操作元素节点
var Dom = new DomCache();
$.each(All_Init_Selectors.split('|'), function(index, selector){
	Dom.setNode(selector, $(selector));
});

// 使用节点
Dom.getNode('#id1').css('color','red');



开发诸如此类的原理的东西,貌似可以完美解决问题,而且代码也很优雅。
但是问题是只有你一个人喜欢自己的代码,熟悉自己写的这种方式。别人估计就还是用jQuery直接来。
代码最后又乱成一团。而且自己还要回头看看Dom.getNode()的参数是否填写正确。


思来想去,干脆直接改jQuery的命名空间了。这样不影响大家使用,而是偷偷的做了点手脚。呵呵呵


开始就把$变量释放出来。
$.noConflict();
又怕没有引进jQuery.所以保险起见写了catch

if($ && $.noConflict) {
	$.noConflict();
} else {
	throw "jQuery not load...";
}

var _$ = $;

重写了$构造函数:

var _cache = {};

$ = function( selector ) {
	return _cache[selector] = _cache[selector] || jQuery(selector);
};

这样他就能记忆所有操作过的元素了。
但是如果$(window) 或者 $(document) 或者 $(this) 就完蛋了。
所以又添加了个判断代码,如果selector是对象参数,就不记忆,直接返回。只记忆字符串

if( jQuery.type(selector) == "string" ){
    return _cache[selector] = _cache[selector] || jQuery(selector);
}else{
	return jQuery(selector);
}

但是jQuery选择器很强大,如果是有上下文的情况下选择元素,比如:$('.class', $('#wrap'));就又完蛋了。

所以再增加了参数唯一的逻辑。

if( arguments.length > 1 ) return jQuery.apply(undefined, arguments);

当然如果本身已经是jQuery对象了,也不需要记忆了,直接返回。

if( selector instanceof jQuery ) return selector;

后来又发现,jQuery选择器也可以当作document.createElement() , 即 $('<div></div>')  ===  $(document.createElement('div'))

所以再增加判断逻辑,如果选择字符串是<>类型的话,就返回不记忆。

if(/^<.+>$/.test(selector)) return jQuery(selector);

现在看起来好多了,没有影响所有人使用习惯。
但是还是少了点东西,就是一般我们还会用到jQuery静态辅助方法。比如$.post $.ajax $.extend 之类的。

所以加段代码:

jQuery.extend($, jQuery);

//覆盖noConflict 但是没有重写jQuery本身的noConflict方法
$.noConflict = function() {
    $ = _$;
};

这样就可以用了。

慢着,还差一个很隐蔽的细节。就是如果我们在dom里面remove掉一个节点的话,那么缓存里面就应该清除才对。
不然就无法找到新插入的节点了。

var _fnnames = "remove insertAfter insertBefore append appendTo";
var _fns = {};
jQuery.each(_fnnames.split(' '), function(k, v){
	_fns[v] = jQuery.fn[v];
	jQuery.fn[v] = function(arg){
		if(!arg && _cache[this.selector]) delete _cache[this.selector];
		if(jQuery.type(arg) === 'boolean' && _cache[this.selector]) delete _cache[this.selector];
		if((arg instanceof jQuery) && _cache[arg.selector]) delete _cache[arg.selector];
		return _fns[v].apply(this, arguments);
	}
});



这样就完美了。整理一下代码:


/*
 * ====================================================
 * 优化jQuery选择器,增加缓存系统。增加console对象兼容IE9-
 */
(function(){

    if($ && $.noConflict) {
        $.noConflict();
    } else {
        throw "jQuery not load...";
    }

    var _$ = $;

    var _cache = {};

    $ = function( selector ) {
        if( arguments.length === 1 && jQuery.type(selector) == "string" && !(/^<.+>$/.test(selector)) ){
            return _cache[selector] = _cache[selector] || jQuery(selector);
        }
        return selector instanceof jQuery ? selector : jQuery.apply(undefined, arguments);
    };

    
	var _fnnames = "remove insertAfter insertBefore append appendTo";

	var _fns = {};

	jQuery.each( _fnnames.split(' '), function( k, v ) {
		_fns[v] = jQuery.fn[v];

		//过滤处理
		jQuery.fn[v] = function(arg){

			// 如果有选择符
			if( this.selector ) {
				// 选择符最后一个名称
				var _last_selector = this.selector.split(' ').pop();
				_cache[_last_selector] && delete _cache[_last_selector];
			}

			// 如果是remove(true)
			if( jQuery.type(arg) === 'boolean' && _cache[this.selector] ) delete _cache[this.selector];

			// 如果是append($('<div></div>').attr('class','abc bdc').attr('id','id1'))
			if( arg && arg instanceof jQuery ){
				if(arg.selector != "") delete _cache[arg.selector];
				var _className = arg.attr('class') || arg.attr('className');
				if(_className){
					jQuery.each(_className.split(' '), function(i, j){
						if(_cache[ '.' + j ]){
							console.log('delete:' + j)
							delete _cache['.' + j];
						} 							
					});
				}
				var _idName = arg.attr('id');
				_idName && _cache['#' + _idName] && delete _cache['#' + _idName];
			}

			//执行原始jQuery函数
			return _fns[v].apply( this, arguments );

		}
	});


    jQuery.extend( $, jQuery );

    $.noConflict = function() {
        $ = _$;
    };

    console = console || {log: $.noop};

})();



至此结束。感觉很蛋疼,就当无聊玩玩吧。









<span style="font-size: 14px; color: rgb(128, 128, 128); font-family: 微软雅黑, Tahoma, 宋体; line-height: 22px;">2群:142601532</span><br style="font-size: 14px; color: rgb(128, 128, 128); font-family: 微软雅黑, Tahoma, 宋体; line-height: 22px;" /><span style="font-size: 14px; color: rgb(128, 128, 128); font-family: 微软雅黑, Tahoma, 宋体; line-height: 22px;">3群:77493278</span><br style="font-size: 14px; color: rgb(128, 128, 128); font-family: 微软雅黑, Tahoma, 宋体; line-height: 22px;" /><span style="font-size: 14px; color: rgb(128, 128, 128); font-family: 微软雅黑, Tahoma, 宋体; line-height: 22px;">4群:70726513</span><br style="font-size: 14px; color: rgb(128, 128, 128); font-family: 微软雅黑, Tahoma, 宋体; line-height: 22px;" /><span style="font-size: 14px; color: rgb(128, 128, 128); font-family: 微软雅黑, Tahoma, 宋体; line-height: 22px;">5群:288256203</span>













0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:21873次
    • 积分:398
    • 等级:
    • 排名:千里之外
    • 原创:16篇
    • 转载:5篇
    • 译文:1篇
    • 评论:3条
    文章分类
    最新评论