我的jQuery代码正在运行,但从程序员的角度来看它是非常糟糕的吗?

时间:2009-11-19 12:28:03

标签: javascript jquery vertical-rhythm

我拼凑了这个jQuery函数。它的目的是计算div.article内所有img元素的边距,以便平衡图像的高度与文档的基线网格,为20像素。为了匹配我的基线网格,每个图像高度应该是20的倍数。如果不是这种情况,例如一个图像的高度为154像素,该函数为img添加了6个像素的边距,以便恢复与基线网格的平衡。

该功能正常运行,所以我的实际问题是:由于我不是程序员,我想知道我的代码是否非常糟糕,尽管它有效,如果是的话,如何改进代码?

jQuery代码:

$('div.article img').each(function() {

    // define line height of CSS baseline grid:
    var line_height = 20;

    // capture the height of the img:
    var img_height = $(this).attr('height');

    // divide img height by line height and round up to get the next integer:
    var img_multiply = Math.ceil(img_height / line_height);

    // calculate the img margin needed to balance the height with the baseline grid:
    var img_margin = (img_multiply * line_height) - img_height;

    // if calculated margin < 5 px:
    if (img_margin < 5) {

        // then add another 20 px to avoid too small whitespace:
        img_margin = img_margin + 20;  
    }

    // if img has caption:
    if ($($(this)).next().length) {

        // then apply margin to caption instead of img:
        $($(this)).next().attr('style', "margin-bottom: " + img_margin + "px;");
    } else {

        // apply margin to img:
        $(this).attr('style', "margin-bottom: " + img_margin + "px;");
    }
});

HTML代码示例,img标题:

<div class="article">
   <!-- [...] -->
    <p class="image">
        <img src="http://example.com/images/123.jpg" width="230" height="154" alt="Image alt text goes here" />
        <small>Image Caption Goes Here</small>
    </p>
   <!-- [...] -->
</div>

HTML代码示例,img无标题:

<div class="article">
    <!-- [...] -->
    <p class="image">
        <img src="http://example.com/images/123.jpg" width="230" height="154" alt="Image alt text goes here" />
    </p>
   <!-- [...] -->
</div>

编辑:基于Russ Cam建议的精炼代码:

var line_height = 20;
var min_margin = 5;
$('div.article img').each(function() {
    var $this = $(this); // prefixed variable name with $ to remind it's a jQuery object
    var img_height = $this.height();
    var img_margin = ((Math.ceil(img_height / line_height)) * line_height) - img_height;
    img_margin = (img_margin < min_margin)? img_margin + line_height : img_margin;
    if ($this.next().length) {      
        $this.next().css({'margin-bottom' : img_margin + 'px'});
    } else {
        $this.css({'margin-bottom' : img_margin + 'px'});
    }
});

7 个答案:

答案 0 :(得分:12)

我可以推荐一些改进

1.cache $(this)each()内的局部变量

$('div.article img').each(function() {

    var $this = $(this); // prefixed variable name with $ 
                         // to remind it's a jQuery object

    // ....

   if ($this.next().length) {

   // ....

   }

});

2.而不是设置attr('style'),请使用css()命令

3.不需要这样做

$($(this))

虽然它不会破坏jQuery,但是将jQuery对象传递给另一个jQuery对象是不必要的。

4.使用$(this).height()$(this).outerHeight()获取浏览器中元素的高度

5.不具体jQuery,但可以使用三元条件运算符来赋值

// if calculated margin < 5 px:
if (img_margin < 5) {

    // then add another 20 px to avoid too small whitespace:
    img_margin = img_margin + 20;  
}

变为

// if calculated margin < 5 px then add another 20 px 
// to avoid too small whitespace
img_margin = (img_margin < 5)? img_margin + 20 : img_margin;  

6.正如Alex在评论中指出的那样,我还会删除那些仅仅重复代码告诉你的多余评论。即使这是调试脚本,在我看来,它们会降低可读性,而注释应仅用于提供读取代码时不具备的细节。

答案 1 :(得分:3)

代码很好。你可以做一些小的改进:

  • 不要在所有地方使用$(this)。尽早将它分配给某些东西并使用它,这样你就不会反复扩展元素。
  • $(this).attr('style', "margin-bottom: " + img_margin + "px;");可以重写为someEl.css('margin-bottom', img_margin + 'px');

答案 2 :(得分:2)

  1. 不应该从元素中获取图像的高度,而是使用$(this)。高度,因为这是浏览器中的真实高度。
  2. 无论如何,它可以重写得更短,比如

    $('div.article').each(function() {
        var img_margin = 20 - $(this).children('img:first').height() % 20;
        if(img_margin < 5) img_margin += 20;
        if($(this).children('small').length > 0)
             $(this).children('small').attr('style', "margin-bottom: " + img_margin + "px;");
        else
             $(this).children('img').attr('style', "margin-bottom: " + img_margin + "px;");
    }
    

答案 3 :(得分:2)

你不应该评论每一行来说明什么是hapening,代码应该告诉你发生了什么。 (除非这是一个非常奇怪的陈述)
应该使用评论告诉你为什么正在完成某些事情。

e.g:

// if img has caption:
if ($($(this)).next().length) {

    // then apply margin to caption instead of img:
    $($(this)).next().attr('style', "margin-bottom: " + img_margin + "px;");
} else {

    // apply margin to img:
    $(this).attr('style', "margin-bottom: " + img_margin + "px;");
}

可以改为,在我眼中更具可读性:

// if img has caption, apply margin to caption instead
if ($($(this)).next().length) {
    $(this).next().css('margin-bottom', img_margin + 'px;');
} else {
    $(this).css('margin-bottom', img_margin + 'px;');
}

答案 4 :(得分:1)

我认为你可以放弃

$($(this))

支持

$(this)

答案 5 :(得分:1)

加速和简化高度计算的方法是:

var img_margin = 20 - ($this.height() % 20);

至少应该有所帮助。

答案 6 :(得分:0)

这是我要做的,在评论中解释

$(function(){

// put this variable out of the loop since it is never modified
    var line_height = 20;

$('div.article img').each(function() {

    // cache $(this) so you don't have to re-access the DOM each time
    var $this = $(this);


    // capture the height of the img - use built-in height()
    var img_height = $this.height();

    // divide img height by line height and round up to get the next integer:
    var img_multiply = Math.ceil(img_height / line_height);

    // calculate the img margin needed to balance the height with the baseline grid:
    var img_margin = (img_multiply * line_height) - img_height;

    // if calculated margin < 5 px:
    if (img_margin < 5) {

        // then add another 20 px to avoid too small whitespace:
    //use ternary operator for concision
        img_margin += 20;  
    }

    // if img has caption:
    if ($this.next().length) {

        // then apply margin to caption instead of img: - use built-in css() function
        $this.next().css("margin-bottom", img_margin);
    } else {

        // apply margin to img:  - use built-in css() function
        $this.css("margin-bottom", img_margin);
    }
});
});