小白读《锋利的jQuery》11章jQuery性能优化和技巧

作者说:当你使用jQuery开发一个复杂的动画和Web应用时,它有可能成为你性能上的终极噩梦。

jQuery性能优化

  1. 使用最新版本的jQuery类库
  2. 使用合适的选择器
    几种常用的选择器
  • $("#id")
    使用id来定位DOM元素无疑是最佳提高性能的方式。
  • $("p"),$("div"),$("input")
    标签选择器是性能优化的第二选择。
  • $(".class")
    对性能产生较大影响,有选择性使用。
  • $("[atrribute = value]")
    性能不理想,为了获得更好的优化效果,建议避免使用。
  • $(":hidden")
    会导致性能问题,不建议使用,若要使用,请先使用ID选择器定位父元素,然后再使用该选择器。
  1. 缓存对象

不良格式:

$("#traffic_light input.on").bind("click", function(){...});
$("#traffic_light input.on").css("border","1px dashed yellow");
$("#traffic_light input.on").css("background-color","orange");
$("#traffic_light input.on").fadeIn("slow");

建议格式

var $active_light = $("#traffic_light input.on");       //缓存变量
$active_light.bind("click", function(){...});
$active_light.css("border","1px dashed yellow");
$active_light.css("background-color","orange");
$active_light.fadeIn("slow");

链式调用更简洁

var $active_light = $("#traffic_light input.on"); 
$active_light.bind("click", function(){...})
            .css({
                "border" : "1px dashed yellow",
                "background-color" : "orange"
            })
            .fadeIn("slow");

如果打算在其他函数中使用jQuery对象,那么可以把它们缓存到全局环境中。

//在全局范围定义一个对象(例如:window对象)
window.$my = {
    head : $("head"),
    traffic_light : $("#traffic_light"),
    traffic_button : $("#traffic_button")
};
function do_something() {
    //现在你可以引用存储的结果并操作它们
    var script = document.createElement("script");
    $my.head.append(script);
    //当你在函数内部操作是,可以继续将查询存入全局对象中去。
    $my.cool_results = $("#some_ul li");
    $my.other_results = $("#some_table td");
    //将全局函数作为一个普通的jquery对象去使用。
    $my.other_results.css("border-color","red");
    $my.traffic_light.css("border-color","green");
}
//你也可以在其他函数中使用它
  1. 循环时的DOM操作

应该将整个元素字符串在插入DOM之前全部创建好

var top_100_list = [...],
   $mylist = $("#mylist"),
   top_100_li = ""; //这个变量将用来存储我们的列表元素
for (var i = 0, l = top_100_list.length; i < l; i++) {
   top_100_li += "<li>" + top_100_list[i] + "</li>";
}    
$mylist.html(top_100_li);
  1. 数组方式使用jQuery对象

在性能方面,建议使用简单的for或者while循环来处理jQuery类库,而不是$.each()。

$.each(array, function (i) {
	array[i] = i;
});

使用for代替each()方法:

var array = new Array();
for (var i = 0; i < array.length; i++) {
	array[i] = i;
}
var $content = $("#content");
if( $content ) {	//总是true
	// Do something
}
if($content.length) {	//拥有元素才返回true
	//Do something
}
  1. 事件代理

把需要多个子元素绑定事件的,把事件绑定到父元素上。

  1. 将你的代码转化成jQuery插件
  2. 使用join()来拼接字符串

不建议用 + 号,用数组的join()方法。

  1. 合理利用HTML5的Data属性

HTML5的data属性可以帮助我们插入数据,特别是前后端的数据交换。

  1. 尽量使用原生的JavaScript方法

  2. 压缩JavaScript

jQuery技巧

  1. 禁用页面的右键菜单
$(document).ready(function () {
    $(document).bind("contextmenu", function (e) {
        return false;
    });
});
  1. 新窗口打开页面
<a href="http://www.cssrain.cn">新窗口</a>

<a href="http://www.cssrain.cn" rel="external">新窗口</a>


<a href="29.扩展String对象的方法.html">当前窗口</a>
<a href="#name">当前窗口</a>


<script>
     $(document).ready(function () {
          //例子1: href=”http://”的超链接将会在新窗口打开链接 
          $('a[href^="http://"]').attr("target", "_blank");

          //例子2: rel="external"的超链接将会在新窗口打开链接  
          $("a[rel$='external']").click(function () {
               this.target = "_blank";
          });
     });
</script>
  1. 判断浏览器类型
$(document).ready(function () {
	// Firefox 2 and above  
	if ($.browser.mozilla && $.browser.version >= "1.8") {
		// do something  
	}
	// Safari  
	if ($.browser.safari) {
		// do something  
	}
	// Chrome  
	if ($.browser.chrome) {
		// do something  
	}
	// Opera  
	if ($.browser.opera) {
		// do something  
	}
	// IE6 and below  
	if ($.browser.msie && $.browser.version <= 6) {
		alert("ie6")
	}
	// anything above IE6  
	if ($.browser.msie && $.browser.version > 6) {
		alert("ie6以上")
	}
});
  1. 输入框文字获取和失去焦点
$(document).ready(function () {
	$("input.text1").val("Enter your search text here.");
	textFill($('input.text1'));
});

function textFill(input) { //input focus text function  
	var originalvalue = input.val();
	input.focus(function () {
		if ($.trim(input.val()) == originalvalue) {
			input.val('');
		}
	}).blur(function () {
		if ($.trim(input.val()) == '') {
			input.val(originalvalue);
		}
	});
}
  1. 返回头部滑动动画
jQuery.fn.scrollTo = function (speed) {
	var targetOffset = $(this).offset().top;
	$('html,body').stop().animate({
		scrollTop: targetOffset
	}, speed);
	return this;
};
// use
$("#goheader").click(function () {
	$("body").scrollTo(500);
	return false;
});
  1. 获取鼠标位置
$(document).ready(function () {
	$(document).mousemove(function (e) {
		$('#XY').html("X : " + e.pageX + " | Y : " + e.pageY);
	});
});
  1. 判断元素是否存在
$(document).ready(function () {
	if ($('#XY').length) {
		alert('元素存在!')
	} else {
		alert('元素不存在!')
	}
});
  1. 点击div也可以跳转
$(document).ready(function () {
	$("div").click(function () {
		window.location = $(this).find("a").attr("href");
		return false;
	});
});
  1. 根据浏览器大小添加不同的样式
$(document).ready(function () {
	function checkWindowSize() {
		if ($(window).width() > 900) {
			$('body').addClass('large');
		} else {
			$('body').removeClass('large');
		}
	}
	$(window).resize(checkWindowSize);
});
  1. 设置div在屏幕中央
$(document).ready(function () {
	jQuery.fn.center = function () {
		this.css("position", "absolute");
		this.css("top", ($(window).height() - this.height()) / 2 + $(window).scrollTop() + "px");
		this.css("left", ($(window).width() - this.width()) / 2 + $(window).scrollLeft() + "px");
		return this;
	}
	//use
	$("#XY").center();
});
  1. 创建自己的选择器
$(document).ready(function () {
   $.extend($.expr[':'], {
       moreThen500px: function (a) {
           return $(a).width() > 500;
       }
   });
   $('.box:moreThen500px').click(function () {
       alert();
   });
});
  1. 关闭所有动画效果
$(document).ready(function () {
	$("#XY1").click(function () {
		animateIt();
	});
	$("#XY2").click(function () {
		jQuery.fx.off = true;
	});
	$("#XY3").click(function () {
		jQuery.fx.off = false;
	});
});

function animateIt() {
	$("#XY").slideToggle("slow");
}
  1. 检测鼠标的右键和左键
$(document).ready(function () {
	$("#XY").mousedown(function (e) {
		alert(e.which) // 1 = 鼠标左键 ; 2 = 鼠标中键; 3 = 鼠标右键
	})
});
  1. 回车提交表单
$(document).ready(function () {
	$("input").keyup(function (e) {
		if (e.which == "13") {
			alert("回车提交!")
		}
	})
});
  1. 设置全局Ajax参数
$(document).ready(function () {
	$('#send1').click(function () {
		$.getJSON(
			"http://api.flickr.com/services/feeds/photos_public.gne?tags=car&tagmode=any&format=json&jsoncallback=?",
			function (data) {
				$("#resText1").empty();
				$.each(data.items, function (i, item) {
					$("<img/> ").attr("src", item.media.m).appendTo("#resText1");
					if (i == 3) {
						return false;
					}
				});
			}
		);
	});

	$.ajaxPrefilter(function (options) {
		options.global = true;
	});
	$("#load").ajaxStart(function () {
		showLoading(); //显示loading
		disableButtons(); //禁用按钮
	});
	$("#load").ajaxComplete(function () {
		hideLoading(); //隐藏loading
		enableButtons(); //启用按钮
	});

});

function showLoading() {
	$("#load").show();
}

function hideLoading() {
	$("#load").hide();
}

function disableButtons() {
	$("#send1").attr("disabled", "disabled");
}

function enableButtons() {
	$("#send1").removeAttr("disabled");
}
  1. 获取选中的下拉框
function getObj() {
	var $obj = $('#someElement').find('option:selected');
	alert($obj.val());
}
  1. 切换复选框
var tog = false;
$('button').click(function () {
    $("input[type=checkbox]").attr("checked", !tog);
    tog = !tog;
});
  1. 使用siblings()来选择同辈元素
$('#nav li').click(function () {
	$(this).addClass('active')
		.siblings().removeClass('active');
});
  1. 个性化链接
$(document).ready(function () {
	$("a[href$='pdf']").addClass("pdf");
	$("a[href$='zip']").addClass("zip");
	$("a[href$='psd']").addClass("psd");
});
  1. 在一段时间之后自动隐藏或关闭元素
$(document).ready(function () {
	$("button").click(function () {
		$("div").slideUp(300).delay(3000).fadeIn(400);
	});
	/*
	//这是1.3.2中我们使用setTimeout来实现的方式
	setTimeout(function() {
		$('div').fadeIn(400)
	}, 3000);
	*/
	//而在1.4之后的版本可以使用delay()这一功能来实现的方式
	//$("div").slideUp(300).delay(3000).fadeIn(400);
});
  1. 使用Firefox和Firebug来记录事件日志
// 在firebug上查看
jQuery.log = jQuery.fn.log = function (msg) {
      if (console) {
            console.log("%s: %o", msg, this);
      }
      return this;
};
$(document).ready(function () {
      $("button").click(function () {
            $('#someDiv').hide().log('div被隐藏');
      });
});
  1. 为任何与选择器相匹配的元素绑定事件
$(document).ready(function () {
	/*
	// 为table里面的td元素绑定click事件,不管td元素是一直存在还是动态创建的
	// jQuery 1.4.2之前使用的方式
	$("table").each(function(){ 
	  $("td", this).live("click", function(){ 
	    $(this).toggleClass("hover"); 
	  }); 
	}); 
	// jQuery 1.4.2 使用的方式
	$("table").delegate("td", "click", function(){ 
	  $(this).toggleClass("hover"); 
	});
	*/
	// jQuery 1.7.1使用的方式
	$("table").on("click", "td", function () {
		$(this).toggleClass("hover");
	});

});
  1. 使用css钩子
/*! Copyright (c) 2010 Burin Asavesna (http://helloburin.com)
 * Licensed under the MIT License (LICENSE.txt).
 */
(function ($) {
    // borderRadius get hooks
    var div = document.createElement('div'),
        divStyle = div.style,
        support = $.support,
        dirs = "TopLeft TopRight BottomRight BottomLeft".split(" ");

    // WebKit supports "borderRadius" as well as "WebKitBorderRadius", weird
    support.borderRadius =
        divStyle.MozBorderRadius === '' ? 'MozBorderRadius' :
        (divStyle.MsBorderRadius === '' ? 'MsBorderRadius' :
            (divStyle.WebkitBorderRadius === '' ? 'WebkitBorderRadius' :
                (divStyle.OBorderRadius === '' ? 'OBorderRadius' :
                    (divStyle.borderRadius === '' ? 'BorderRadius' :
                        false))));

    div = null;

    function borderCornerRadius(direction, prefix) {
        prefix = prefix === undefined || prefix === '' ? 'border' : prefix + 'Border';
        if (support.borderRadius && support.borderRadius == "MozBorderRadius") {
            // e.g. MozBorderRadiusTopleft
            return prefix + "Radius" + direction.charAt(0).toUpperCase() + direction.substr(1).toLowerCase();
        } else {
            // e.g. WebKitBorderTopLeftRadius, borderTopLeftRadius, etc
            return prefix + direction + "Radius";
        }
    }

    if (support.borderRadius && support.borderRadius !== "BorderRadius") {
        var vendor_prefix = support.borderRadius.replace('BorderRadius', '');
        $.cssHooks.borderRadius = {
            get: function (elem, computed, extra) {
                // return each of the directions, topleft, topright, bottomright, bottomleft
                return $.map(dirs, function (dir) {
                    return $.css(elem, borderCornerRadius(dir, vendor_prefix));
                }).join(" ");
            },
            set: function (elem, value) {
                // takes in a single value or shorthand (just letting the browser handle this) 
                // e.g. 5px to set all, or 5px 0 0 5px to set left corners
                elem.style[borderCornerRadius('', vendor_prefix)] = value;
            }
        };

        $.each(dirs, function (i, dir) {
            $.cssHooks["borderRadius" + dir] = {
                get: function (elem, computed, extra) {
                    return $.css(elem, borderCornerRadius(dir, vendor_prefix));
                },
                set: function (elem, value) {
                    elem.style[borderCornerRadius(dir, vendor_prefix)] = value;
                }
            };
        });

    }

})(jQuery);

//use
$('#rect').css('borderRadius', 10);
  1. $.proxy()使用

使得回调函数执行完this执行不变。

$('#panel').fadeIn(function () {
    // Using $.proxy :
    $('#panel button').click($.proxy(function () {
        // this 指向 #panel
        $(this).fadeOut();
    }, this));
});
  1. 限制Text-Area域中的字符的个数
jQuery.fn.maxLength = function (max) {
	this.each(function () {
		var type = this.tagName.toLowerCase();
		var inputType = this.type ? this.type.toLowerCase() : null;
		if (type == "input" && inputType == "text" || inputType == "password") {
			//应用标准的maxLength
			this.maxLength = max;
		} else if (type == "textarea") {
			this.onkeypress = function (e) {
				var ob = e || event;
				var keyCode = ob.keyCode;
				var hasSelection = document.selection ? document.selection.createRange().text.length > 0 : this.selectionStart !=
					this.selectionEnd;
				return !(this.value.length >= max && (keyCode > 50 || keyCode == 32 || keyCode == 0 || keyCode == 13) && !ob.ctrlKey &&
					!ob.altKey && !hasSelection);
			};
			this.onkeyup = function () {
				if (this.value.length > max) {
					this.value = this.value.substring(0, max);
				}
			};
		}
	});
};
//use
$('#mytextarea').maxLength(10);
  1. 本地存储
localStorage.someData = "This is going to be saved";
  1. 解析json数据时报parseError错误
{
	"key" : "28CATEGORY",
	"status" : "0"
}
  1. 从元素中除去HTML
(function ($) {
    $.fn.stripHtml = function () {
        var regexp = /<("[^"]*"|'[^']*'|[^'">])*>/gi;
        this.each(function () {
            $(this).html($(this).html().replace(regexp, ''));
        });
        return $(this);
    }
})(jQuery);
//用法: 
$('div').stripHtml();
  1. 扩展String对象的方法
$.extend(String.prototype, {
	isPositiveInteger: function () {
		return (new RegExp(/^[1-9]\d*$/).test(this));
	},
	isInteger: function () {
		return (new RegExp(/^\d+$/).test(this));
	},
	isNumber: function (value, element) {
		return (new RegExp(/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/).test(this));
	},
	trim: function () {
		return this.replace(/(^\s*)|(\s*$)|\r|\n/g, "");
	},
	trans: function () {
		return this.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"');
	},
	replaceAll: function (os, ns) {
		return this.replace(new RegExp(os, "gm"), ns);
	},
	skipChar: function (ch) {
		if (!this || this.length === 0) {
			return '';
		}
		if (this.charAt(0) === ch) {
			return this.substring(1).skipChar(ch);
		}
		return this;
	},
	isValidPwd: function () {
		return (new RegExp(/^([_]|[a-zA-Z0-9]){6,32}$/).test(this));
	},
	isValidMail: function () {
		return (new RegExp(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(this.trim()));
	},
	isSpaces: function () {
		for (var i = 0; i < this.length; i += 1) {
			var ch = this.charAt(i);
			if (ch != ' ' && ch != "\n" && ch != "\t" && ch != "\r") {
				return false;
			}
		}
		return true;
	},
	isPhone: function () {
		return (new RegExp(/(^([0-9]{3,4}[-])?\d{3,8}(-\d{1,6})?$)|(^\([0-9]{3,4}\)\d{3,8}(\(\d{1,6}\))?$)|(^\d{3,8}$)/)
			.test(this));
	},
	isUrl: function () {
		return (new RegExp(/^[a-zA-z]+:\/\/([a-zA-Z0-9\-\.]+)([-\w .\/?%&=:]*)$/).test(this));
	},
	isExternalUrl: function () {
		return this.isUrl() && this.indexOf("://" + document.domain) == -1;
	}
});

$("button").click(function () {
	alert($("input").val().isInteger());
});

猜你喜欢

转载自blog.csdn.net/canxuezhang/article/details/87727697