最近做了一个模块,实际很简单,用到了jquery,但是现在真是觉得js很复杂.很难控制与调试.代码太过灵活却很难理解.先说问题.我在页面上显示一颗树,用到了jquery的插件treeview.并且要在树上加右键菜单,用到了contextmenu.
最开始的做法.把要生成数的集合,包括所有的节点,子节点,一次性的传到页面,然后页面做个循环生成treeview要求的ui li的形式, js语句很简单,就是显示树要用的
$("#tree").treeview({
collapsed: true,
animated: "medium",
control:"#sidetreecontrol",
prerendered: true,
persist: "location"
});
和 加载右键菜单的:
$("strong").each(function(){
$(this).contextMenu(menu1);
});
把需要绑定右键菜单的元素,这里是所有的strong节点.
最开始是没有问题的,但是后来要求要加一些节点,问题来了,树的加载非常的慢.浏览器要死在那大概30妙.我最开始觉得可能节点多了,那么后台把数据一次传过来,页面做的那个循环可能是问题所在.
于是我把它改成了ajax的形式,已开始先加载最顶上的一层.当用户点击节点的时候再把下面的子节点展现出来.但是却仍然没有改善.我就觉得很奇怪了.我不用ie,换成safari,页面很快加载出来,没延迟.但我不可能去换浏览器来解决这个问题阿.那么可能就是那连个jquery的插件问题了.我只有钻进去看哪些晦涩难懂的代码.
我一直把注意力集中在那个treeview上.因为是树的显示慢嘛..但是,当我用ajax只显示最上层的时候,实际上就不应该很慢了,而且他对所有的li偏历也是不可避免的.
只剩下了contextmenu了.最终发现这样一段代码.
$.fn.contextMenu = function(menu,options) {
var cmenu = $.contextMenu.create(menu,options);
return this.each(function(){
$(this).bind('contextmenu',function(e){cmenu.show(this,e);return false;});
});
问题就出在这句话上.在我之前做$(this).contextMenu(menu1);的时候他就会对所有的节点进行偏历,而后每个节点执行了create这个方法,这个方法做的事情可多,他会用js先把你的右键菜单组装好.我把这句话移到bind里面就好了,因为他只有在用户右键点击的时候才加载.
罗唆完了,总结
1)ie非常垃圾,虽然这个代码确实没写好,但是 ie和其他浏览器比起来在js解析的速度上确实差太多,(我用的IE7).我主流的浏览器都测过,chrome和safari最快,firefox其次,ie 垫底.
2)关于页面相应速度的问题,浏览器负责解析html和js. 一般很多人和我一样遇到这种问题首先想到的是不是页面上加载的信息过长,这个的确是一个原因,传的数据量大,首先后台计算时间长,其次网络的传输慢,最后加上浏览器的解析,的确会慢.但是实际上这个时候很多的压力都分给了后台.页面看起来先是一片白,然后过一会加载成功.
还有个原因就是js,我们现在崇尚的是把js和html分开,那不可避免,特别是jquery 的很多写法要对html进行便历,这在特别是ie中很慢.现象是页面很快显示出来,但是不能操作,是死的,下面的进度条一直在.
所以在显示中,如果应用面对很快的浏览器,那么很多的功能因该放在js中来做,分担服务器的压力,但是如果浏览器很慢效果就不一定好了,特别现在都很流行用js在页面中动态加载节点,节点一多就要挂.
3)ajax的陷阱.顺便谈到ajax的引用,ajax实际上可以分为异步和同步,这都可以设置.实际上异步是很危险的.
举个例子.
var test="";
$.getJSON(settings.url, {root: root}, function(response) {
test="1";
}
这个时候执行完了test 还是为空的,因为在ajax还为返回的时候页面就执行了到了$.getJSON之下的语句了.
4)页面的加载顺序,这个对js 也很有影响,如果你的js要操作dom,但是你的js 却是在dom加载之前就加载了,那么这些js 是无用的.
在jquery中很多插件都是这样写的:
(function($){
........ //插件代码
})(jQuery);
这句话实际上在页面进来是最先开始执行的,先于dom的加载.所以这里你可以加载一些预先定义好的function阿,对象什么的.但不能有操作dom的操作.
我们常用的:
$(document).ready(function() {
.........
})
是在所有的dom节点加载完后执行.所以对dom的操作都放这里.
window.onload.则是最后执行,要等图片之类的加载完了财执行.
5)用过怎么多jquery的插件,很少能有完全满足自己需求的,必须要自己改些东西,所以知道一些jquery插件的写法也很有必要.
贴下代码就明白了:
(function($) { $.fn.extend({ alertName : function(setting){ alert(this.text()+setting.name); } }); $.extend({ globeAlertName : function(){ alert("fuck"); } }); })(jQuery);
这个可以扩展jquery的方法.两者的区别呢,看调用的方式:
$(document).ready(function(){ $("#tt").alertName({name : "suyu"}); $.globeAlertName(); });
看出不同了吗.一个是全局对象,一个要用在dom上.