杨二

Machine repeats, Human creates

jQuery最佳实践

jquery

前言

使用jQuery已经有两年,其API用起来非常的爽,甚至都成为了事实上的标准,以至于好多前端小白把jQuery等同于Javascript。虽然jQuery的普及度很高,但遵循最佳实践来写jQuery代码的却寥寥无几,下面就自己在工作的积累来写一些jQuery的最佳实践(也有从网络上搜集的)。

加载jQuery

  • 使用CDN加载,去掉http:或者https:,同时做好本地fallback。

        <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
        
        <script>window.jQuery || document.write('<script src="js/jquery-2.1.4.min.js" type="text/javascript"></script>')</script>
  • 如果可能,请在底部加载jQuery外部文件

  • 有关版本问题

    • 如果需要支持Internet Explorer 6/7/8,那就不要使用2.x
    • 对于web app,请大胆使用最新版本的jQuery,当然,也可以选择zepto.js
    • 不要使用jquery-last.js CDN
  • 检测浏览器特性,请用Modernizr

变量

  • 所有的jQuery对象命名最好加个$前缀加以区分
  • 缓存通过选择符获取的jQuery对象,以待复用:

        
        var $myDiv = $("#myDiv");
        
        $myDiv.click(function(){...});

DOM操作

  • 对于一些较为复杂的DOM操作,可以先.detach(),原因参考此处

        
        var $myList = $("#list-container > ul").detach();
        
        //...在$myList上做了一系列复杂的操作后...
        
        $myList.appendTo("#list-container");
  • 链式调用

    • 链式调用让代码更具可读性

          
          $("#myDiv").addClass("error").show();
    • 当调用过多时,注意合理加缩进,时刻维持代码可读性

          
          $("#myLink")
          
              .addClass("bold")
          
              .on("click", myClickHandler)
          
              .on("mouseover", myMouseOverHandler)
          
              .show();
          
    #选择器
  • 尽可能使用ID选择器,因为jQuery源码中调用的是document.getElementById()

  • 当使用类选择器时,没必要再附加元素标签了

        
        var $products = $("div.products"); // SLOW
        
        var $products = $(".products"); // FAST
  • 对于像Id->Child这样的嵌套选择器,使用.find()性能更好些,因为id选择器不走Sizzle引擎,这能节约一些性能损耗。

        // BAD, 全部走的Sizzle选择器引擎
        
        var $productIds = $("#products div.id");
        
        // GOOD, #products 走的是document.getElementById(),因此只有div.id走Sizzle 选择器引擎
        
        var $productIds = $("#products").find("div.id");
  • 选择器父类越模糊越好,子类越详细越好。参考此处

        
        // 未经优化的
        
        $("div.data .gonzalez");
        
        // 优化后的
        
        $(".data td.gonzalez");
  • 给选择器以上下文

        // SLOWER 遍历了整个文档的class
        
        $('.class');
        
        // FASTER 只在#class-container下遍历
        
        $('.class', '#class-container');
  • 避免使用通配符*

        
        $('div.container > *'); // BAD
        
        $('div.container').children(); // BETTER
  • 没有必要嵌套或组合使用ID选择器

        $('#outer #inner'); // BAD
        $('div#inner'); // BAD
        $('.outer-container #inner'); // BAD
        $('#inner'); // GOOD,  document.getElementById()搞定一切

事件

  • 每个页面有且仅有一个DOMReady事件,便于调试。

  • 尽量不要使用匿名函数来用作事件处理,因为不利于调试,测试,维护和复用。

        // BAD
        $("#myLink").on("click", function(){...}); 
        // GOOD
        function myLinkClickHandler(){...}
        $("#myLink").on("click", myLinkClickHandler);
  • 避免HTML结构中声明并绑定事件处理函数,这非常不利于调试,也破坏了HTML紧做结构表现的职责。

        <!-- BAD -->
        <a id="myLink" href="#" onclick="myEventHandler();">my link</a>
        
        $("#myLink").on("click", myEventHandler); // GOOD
  • 使用事件代理机制,一个明显的好处就是当有新子元素插入时,不用重新绑定事件,参考此处

    $("#list a").on("click", myClickHandler); // BAD, 相当于给list下的所有a元素都绑定了click事件.
    
    $("#list").on("click", "a", myClickHandler); //GOOD, 只给父元素list绑定了click事件.

Ajax

  • 熟习$.ajax(),尽量不要用.get(),.getJson()这样的简洁方式。

        //ajax模板
        var jqxhr = $.ajax({
            url: url,
            type: "POST", // 默认GET
            cache: true, // 默认true, 但对于dataType为'script'或者'jsonp',则为false
            data: {}, // 请求附带的参数
            dataType: "json", 
            jsonp: "callback", // 指定回调参数的名称
            statusCode: { // 在此指定相应的响应状态的回调函数
                404: handler404,
                500: handler500
            }
        });
        jqxhr.done(successHandler);
        jqxhr.fail(failureHandler);
  • 请求地址最好用无协议的URL,即去除http:/https:

  • 使用data对象传送数据,而非附加在URL里

        // 可读性不好...
        $.ajax({
            url: "something.php?param1=test1&param2=test2",
            ....
        });
        // 更具可读性...
        $.ajax({
            url: "something.php",
            data: { param1: test1, param2: test2 }
        });
  • 使用Promise风格,例子

        $.ajax({ ... }).then(successHandler, failureHandler);
        // OR
        var jqxhr = $.ajax({ ... });
        jqxhr.done(successHandler);
        jqxhr.fail(failureHandler);

动画效果

  • 不要滥用动画效果,或者干脆不用,直到PM有切实需求。
  • 如果用动画,优先使用像show/hideslideUp/slideDown这样的简单API

插件

  • 优先考虑有良好文档,有测试用例,有社区支持的插件
  • 使用插件前不要忘记检测与你正在使用的jQuery版本是否冲突
  • 任何可复用的组件都应该插件化,这里有个插件模板

其他

  • 使用对象字面量设置特性

        // BAD
        $myLink.attr("href", "#").attr("title", "my link").attr("rel", "external"); // 
        // GOOD
        $myLink.attr({
            href: "#",
            title: "my link",
            rel: "external"
        });
  • 避免使用jQuery添加CSS

        // BAD
        $("#mydiv").css({'color':red, 'font-weight':'bold'}); // BAD

    定义好CSS rule

        .error { color: red; font-weight: bold; } /\* GOOD */

    然后通过jQuery添加class

        $("#mydiv").addClass("error"); // GOOD

优秀资源