作者说:当你使用jQuery开发一个复杂的动画和Web应用时,它有可能成为你性能上的终极噩梦。
jQuery性能优化
- 使用最新版本的jQuery类库
- 使用合适的选择器
几种常用的选择器
- $("#id")
使用id来定位DOM元素无疑是最佳提高性能的方式。 -
$("p"),$("div"),$("input")
标签选择器是性能优化的第二选择。 - $(".class")
对性能产生较大影响,有选择性使用。 - $("[atrribute = value]")
性能不理想,为了获得更好的优化效果,建议避免使用。 - $(":hidden")
会导致性能问题,不建议使用,若要使用,请先使用ID选择器定位父元素,然后再使用该选择器。
- 缓存对象
不良格式:
$("#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");
}
//你也可以在其他函数中使用它
- 循环时的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);
- 数组方式使用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
}
- 事件代理
把需要多个子元素绑定事件的,把事件绑定到父元素上。
- 将你的代码转化成jQuery插件
- 使用join()来拼接字符串
不建议用 + 号,用数组的join()方法。
- 合理利用HTML5的Data属性
HTML5的data属性可以帮助我们插入数据,特别是前后端的数据交换。
-
尽量使用原生的JavaScript方法
-
压缩JavaScript
jQuery技巧
- 禁用页面的右键菜单
$(document).ready(function () {
$(document).bind("contextmenu", function (e) {
return false;
});
});
- 新窗口打开页面
<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>
- 判断浏览器类型
$(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以上")
}
});
- 输入框文字获取和失去焦点
$(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);
}
});
}
- 返回头部滑动动画
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;
});
- 获取鼠标位置
$(document).ready(function () {
$(document).mousemove(function (e) {
$('#XY').html("X : " + e.pageX + " | Y : " + e.pageY);
});
});
- 判断元素是否存在
$(document).ready(function () {
if ($('#XY').length) {
alert('元素存在!')
} else {
alert('元素不存在!')
}
});
- 点击div也可以跳转
$(document).ready(function () {
$("div").click(function () {
window.location = $(this).find("a").attr("href");
return false;
});
});
- 根据浏览器大小添加不同的样式
$(document).ready(function () {
function checkWindowSize() {
if ($(window).width() > 900) {
$('body').addClass('large');
} else {
$('body').removeClass('large');
}
}
$(window).resize(checkWindowSize);
});
- 设置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();
});
- 创建自己的选择器
$(document).ready(function () {
$.extend($.expr[':'], {
moreThen500px: function (a) {
return $(a).width() > 500;
}
});
$('.box:moreThen500px').click(function () {
alert();
});
});
- 关闭所有动画效果
$(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");
}
- 检测鼠标的右键和左键
$(document).ready(function () {
$("#XY").mousedown(function (e) {
alert(e.which) // 1 = 鼠标左键 ; 2 = 鼠标中键; 3 = 鼠标右键
})
});
- 回车提交表单
$(document).ready(function () {
$("input").keyup(function (e) {
if (e.which == "13") {
alert("回车提交!")
}
})
});
- 设置全局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");
}
- 获取选中的下拉框
function getObj() {
var $obj = $('#someElement').find('option:selected');
alert($obj.val());
}
- 切换复选框
var tog = false;
$('button').click(function () {
$("input[type=checkbox]").attr("checked", !tog);
tog = !tog;
});
- 使用siblings()来选择同辈元素
$('#nav li').click(function () {
$(this).addClass('active')
.siblings().removeClass('active');
});
- 个性化链接
$(document).ready(function () {
$("a[href$='pdf']").addClass("pdf");
$("a[href$='zip']").addClass("zip");
$("a[href$='psd']").addClass("psd");
});
- 在一段时间之后自动隐藏或关闭元素
$(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);
});
- 使用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被隐藏');
});
});
- 为任何与选择器相匹配的元素绑定事件
$(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");
});
});
- 使用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);
- $.proxy()使用
使得回调函数执行完this执行不变。
$('#panel').fadeIn(function () {
// Using $.proxy :
$('#panel button').click($.proxy(function () {
// this 指向 #panel
$(this).fadeOut();
}, this));
});
- 限制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);
- 本地存储
localStorage.someData = "This is going to be saved";
- 解析json数据时报parseError错误
{
"key" : "28CATEGORY",
"status" : "0"
}
- 从元素中除去HTML
(function ($) {
$.fn.stripHtml = function () {
var regexp = /<("[^"]*"|'[^']*'|[^'">])*>/gi;
this.each(function () {
$(this).html($(this).html().replace(regexp, ''));
});
return $(this);
}
})(jQuery);
//用法:
$('div').stripHtml();
- 扩展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(/</g, '<').replace(/>/g, '>').replace(/"/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());
});