DRY - 如何组合这些jQuery函数?

时间:2014-01-04 20:17:49

标签: javascript jquery

原始问题:

我正在看这个极为强大的代码块,我知道它可以缩减约90%。我只是想不出怎么做。

这是我所指的块:

$('table.model a').click(function(){
var divForm = [$('div.form')];
$(this).closest('div').not('.close').fadeOut(500).animate({"top": "-414px"}, 100).fadeIn('fast');
    if ($(this).hasClass('tmi48')) {
        $('img.i4').show();
        $('h1.tmi48').show();
    } else if ($(this).hasClass('tmi416')) {
        $('img.i4').show();
        $('h1.tmi416').show();
    } else if ($(this).hasClass('tmi432')) {
        $('img.i4').show();
        $('h1.tmi432').show();
    } else if ($(this).hasClass('tmi464')) {
        $('img.i4').show();
        $('h1.tmi464').show();
    } else if ($(this).hasClass('tmi4s16')) {
        $('img.i4s').show();
        $('h1.tmi4s16').show();
    } else if ($(this).hasClass('tmi4s32')) {
        $('img.i4s').show();
        $('h1.tmi4s32').show();
    } else if ($(this).hasClass('tmi4s64')) {
        $('img.i4s').show();
        $('h1.tmi4s64').show();
    } else if ($(this).hasClass('tmi516')) {
        $('img.i5').show();
        $('h1.tmi516').show();
    } else if ($(this).hasClass('tmi532')) {
        $('img.i5').show();
        $('h1.tmi532').show();
    } else if ($(this).hasClass('tmi564')) {
        $('img.i5').show();
        $('h1.tmi564').show();
    } else if ($(this).hasClass('tmi5c16')) {
        $('img.i5c').show();
        $('h1.tmi5c16').show();
    } else if ($(this).hasClass('tmi5c32')) {
        $('img.i5c').show();
        $('h1.tmi5c32').show();
    } else if ($(this).hasClass('tmi5c64')) {
        $('img.i5c').show();
        $('h1.tmi5c64').show();
    } else if ($(this).hasClass('tmi5s16')) {
        $('img.i5s').show();
        $('h1.tmi5s16').show();
    } else if ($(this).hasClass('tmi5s32')) {
        $('img.i5s').show();
        $('h1.tmi5s32').show();
    } else if ($(this).hasClass('tmi5s64')) {
        $('img.i5s').show();
        $('h1.tmi5s64').show();
    } else if ($(this).hasClass('atti48')) {
        $('img.i4').show();
        $('h1.atti48').show();
    } else if ($(this).hasClass('atti416')) {
        $('img.i4').show();
        $('h1.atti416').show();
    } else if ($(this).hasClass('atti432')) {
        $('img.i4').show();
        $('h1.atti432').show();
    } else if ($(this).hasClass('atti464')) {
        $('img.i4').show();
        $('h1.atti464').show();
    } else if ($(this).hasClass('atti4s16')) {
        $('img.i4s').show();
        $('h1.atti4s16').show();
    } else if ($(this).hasClass('atti4s32')) {
        $('img.i4s').show();
        $('h1.atti4s32').show();
    } else if ($(this).hasClass('atti4s64')) {
        $('img.i4s').show();
        $('h1.atti4s64').show();
    } else if ($(this).hasClass('atti516')) {
        $('img.i5').show();
        $('h1.atti516').show();
    } else if ($(this).hasClass('atti532')) {
        $('img.i5').show();
        $('h1.atti532').show();
    } else if ($(this).hasClass('atti564')) {
        $('img.i5').show();
        $('h1.atti564').show();
    } else if ($(this).hasClass('atti5c16')) {
        $('img.i5c').show();
        $('h1.atti5c16').show();
    } else if ($(this).hasClass('atti5c32')) {
        $('img.i5c').show();
        $('h1.atti5c32').show();
    } else if ($(this).hasClass('atti5c64')) {
        $('img.i5c').show();
        $('h1.atti5c64').show();
    } else if ($(this).hasClass('atti5s16')) {
        $('img.i5s').show();
        $('h1.atti5s16').show();
    } else if ($(this).hasClass('atti5s32')) {
        $('img.i5s').show();
        $('h1.atti5s32').show();
    } else if ($(this).hasClass('atti5s64')) {
        $('img.i5s').show();
        $('h1.atti5s64').show();
    } else if ($(this).hasClass('vzi48')) {
        $('img.i4').show();
        $('h1.vzi48').show();
    } else if ($(this).hasClass('vzi416')) {
        $('img.i4').show();
        $('h1.vzi416').show();
    } else if ($(this).hasClass('vzi432')) {
        $('img.i4').show();
        $('h1.vzi432').show();
    } else if ($(this).hasClass('vzi464')) {
        $('img.i4').show();
        $('h1.vzi464').show();
    } else if ($(this).hasClass('vzi4s16')) {
        $('img.i4s').show();
        $('h1.vzi4s16').show();
    } else if ($(this).hasClass('vzi4s32')) {
        $('img.i4s').show();
        $('h1.vzi4s32').show();
    } else if ($(this).hasClass('vzi4s64')) {
        $('img.i4s').show();
        $('h1.vzi4s64').show();
    } else if ($(this).hasClass('vzi516')) {
        $('img.i5').show();
        $('h1.vzi516').show();
    } else if ($(this).hasClass('vzi532')) {
        $('img.i5').show();
        $('h1.vzi532').show();
    } else if ($(this).hasClass('vzi564')) {
        $('img.i5').show();
        $('h1.vzi564').show();
    } else if ($(this).hasClass('vzi5c16')) {
        $('img.i5c').show();
        $('h1.vzi5c16').show();
    } else if ($(this).hasClass('vzi5c32')) {
        $('img.i5c').show();
        $('h1.vzi5c32').show();
    } else if ($(this).hasClass('vzi5c64')) {
        $('img.i5c').show();
        $('h1.vzi5c64').show();
    } else if ($(this).hasClass('vzi5s16')) {
        $('img.i5s').show();
        $('h1.vzi5s16').show();
    } else if ($(this).hasClass('vzi5s32')) {
        $('img.i5s').show();
        $('h1.vzi5s32').show();
    } else if ($(this).hasClass('vzi5s64')) {
        $('img.i5s').show();
        $('h1.vzi5s64').show();
    } else if ($(this).hasClass('uli48')) {
        $('img.i4').show();
        $('h1.uli48').show();
    } else if ($(this).hasClass('uli416')) {
        $('img.i4').show();
        $('h1.uli416').show();
    } else if ($(this).hasClass('uli432')) {
        $('img.i4').show();
        $('h1.uli432').show();
    } else if ($(this).hasClass('uli464')) {
        $('img.i4').show();
        $('h1.uli464').show();
    } else if ($(this).hasClass('uli4s16')) {
        $('img.i4s').show();
        $('h1.uli4s16').show();
    } else if ($(this).hasClass('uli4s32')) {
        $('img.i4s').show();
        $('h1.uli4s32').show();
    } else if ($(this).hasClass('uli4s64')) {
        $('img.i4s').show();
        $('h1.uli4s64').show();
    } else {
        return;
    }
    divForm[0].animate({"top": "+=557px"}, 500, function(){
        $(this).animate({"top": "-=20px"}, 200);
    }); 
});

这是jsFiddle:http://jsfiddle.net/6YUuT/

正如您所看到的,每个链接都调用相同的表单,但标题和图像会根据点击的链接而改变。我尝试过使用共享类,但我无法提出修复这很有效。

REVISIONS&新问题:

我几乎已经完成了所有功能,但我遇到了原来的问题,这次是在另一个地方。我有另外一个需要消失的巨大代码块,虽然它看起来几乎与上一个相同,但它已经不同了,我还没有能够提出一个有效的解决方案。

这是jsFiddle:http://jsfiddle.net/9Pr8L/

违规/攻击性代码块:

function linkHide() {
    //var r = /(?:^| )((?:tm|att|vz|sp|ul)(app?|bb?|htc?|lg?|mot?|sam?))(?: |$)/;
    if ($('span.tm').is(':visible') && $('span.app').is(':visible')) {
        $('td.tmapp').show();
    } 
    if ($('span.tm').is(':visible') && $('span.bb').is(':visible')) {
        $('td.tmbb').show();
    }
    if ($('span.tm').is(':visible') && $('span.htc').is(':visible')) {
        $('td.tmhtc').show();
    }
    if ($('span.tm').is(':visible') && $('span.lg').is(':visible')) {
        $('td.tmlg').show();
    }
    if ($('span.tm').is(':visible') && $('span.mot').is(':visible')) {
        $('td.tmmot').show();
    }
    if ($('span.tm').is(':visible') && $('span.sam').is(':visible')) {
        $('td.tmsam').show();
    }
    if ($('span.att').is(':visible') && $('span.app').is(':visible')) {
        $('td.attapp').show();
    }
    if ($('span.att').is(':visible') && $('span.bb').is(':visible')) {
        $('td.attbb').show();
    }
    if ($('span.att').is(':visible') && $('span.htc').is(':visible')) {
        $('td.atthtc').show();
    }
    if ($('span.att').is(':visible') && $('span.lg').is(':visible')) {
        $('td.attlg').show();
    }
    if ($('span.att').is(':visible') && $('span.mot').is(':visible')) {
        $('td.attmot').show();
    }
    if ($('span.att').is(':visible') && $('span.sam').is(':visible')) {
        $('td.attsam').show();
    }
    if ($('span.vz').is(':visible') && $('span.app').is(':visible')) {
        $('td.vzapp').show();
    }
    if ($('span.vz').is(':visible') && $('span.bb').is(':visible')) {
        $('td.vzbb').show();
    }
    if ($('span.vz').is(':visible') && $('span.htc').is(':visible')) {
        $('td.vzhtc').show();
    }
    if ($('span.vz').is(':visible') && $('span.lg').is(':visible')) {
        $('td.vzlg').show();
    }
    if ($('span.vz').is(':visible') && $('span.mot').is(':visible')) {
        $('td.vzmot').show();
    }
    if ($('span.vz').is(':visible') && $('span.sam').is(':visible')) {
        $('td.vzsam').show();
    }
    if ($('span.ul').is(':visible') && $('span.app').is(':visible')) {
        $('td.ulapp').show();
    }
    if ($('span.ul').is(':visible') && $('span.bb').is(':visible')) {
        $('td.ulbb').show();
    }
    if ($('span.ul').is(':visible') && $('span.htc').is(':visible')) {
        $('td.ulhtc').show();
    }
    if ($('span.ul').is(':visible') && $('span.lg').is(':visible')) {
        $('td.ullg').show();
    }
    if ($('span.ul').is(':visible') && $('span.mot').is(':visible')) {
        $('td.ulmot').show();
    }
    if ($('span.ul').is(':visible') && $('span.sam').is(':visible')) {
        $('td.ulsam').show();
    }
};

我现在已经缩减了HTML,以便所有表数据都存在于一个包含可变标题,图像和链接的表中。我能够编辑wared的正则表达式,以便它返回正确的字符串,但我想不出实际使用它的方法。

5 个答案:

答案 0 :(得分:5)

我假设每个锚只能有一个这样的类。在这种情况下,正则表达式允许您从类属性中提取此类,并同时从中提取图像类(this引用锚元素):

var r = /(?:^| )((?:tm|att|vz|ul)(i\d[a-z]?)\d\d?)(?: |$)/;
var m = $(this).attr('class').match(r);
if (m) {
    $('img.' + m[2]).show();
    $('h1.' + m[1]).show();
} else {
    return;
}

正则表达式:

(?:^| )            the beginning of the string or a whitespace
(...)              capture -> group 1 : the heading class
(?:tm|att|vz|ul)   any of these prefixes, one time
(...)              capture -> group 2 : the image class
i\d[a-z]?          "i" + one digit + any letter, zero or one times
\d\d?              one or two digits
(?: |$)            a whitespace or the end of the string

总结:

"tm" or "att" or "vz" or "ul"
+ "i" + one digit + zero or one letter (group 2, example : "i4s")
+ one or two digits

这将匹配tmi416atti4s16vzi48等字符串。为了使事情更加清晰,您可以打开浏览器控制台并将以下代码粘贴到其中:

'foo atti4s16 bar'.match(
    /(?:^| )((?:tm|att|vz|ul)(i\d[a-z]?)\d\d?)(?: |$)/
)

您可以看到返回的数组包含标题类(索引1 =组1)和图像类(索引2 =组2):

[" atti4s16 ", "atti4s16", "i4s"]

答案 1 :(得分:2)

现在您的问题完全不同了,这里进一步优化,再次将大部分数据放入数据结构中,然后通过循环数据结构来避免重复代码:

function linkHide() {

    var atts = ["tm", "att", "vz", "ul"];
    var mfrs = ["app", "bb", "htc", "lg", "mot", "sam"];

    for (var i = 0; i < atts.length; i++) {
        if ($("span." + atts[i]).is(':visible')) {
            for (var j = 0; j < mfrs.length; j++) {
                if ($("span." + mfrs[j]).is(':visible')) {
                    $("td" + "." + atts[i] + mfrs[j]).show();
                }
            }                
        }
    } 
};

这是原始问题的答案,现在已完成更改/编辑到不同的内容:

您可以将所有类放在一个数组中,然后遍历数组以将其压缩为:

$('table.model a').click(function(){
    var classList = ['tmi416', 'tmi432', ... put other classes here];
    var divForm = [$('div.form')];
    var self = $(this);
    self.closest('div').not('.close').fadeOut(500).animate({"top": "-414px"}, 100).fadeIn('fast');
    for (var i = 0; i < classList.length; i++) {
        if (self.hasClass(classList[i])) {
            // figure out class name to show
            // algorithm is to remove chars before first "i" and 
                    //    then remove trailing 16,32 or 64
            var name = classList[i].replace(/^.*?i/, "i").replace(/16$|32$|64$/,"");
            $(".img." + name).show();
            $("h1." + classList[i]).show();
            break;
        }
    }
    divForm[0].animate({"top": "+=557px"}, 500, function(){
        $(this).animate({"top": "-=20px"}, 200);
    }); 
});

或者,如果你在目标类名上加上"xxx-"的公共前缀,你就可以这样做,而不必提前构建一长串的类名:

$('table.model a').click(function(){
    var divForm = [$('div.form')];
    var self = $(this);
    self.closest('div').not('.close').fadeOut(500).animate({"top": "-414px"}, 100).fadeIn('fast');
    var classes = " " + this.className + " ";
    var match = classes.match(/\sxxx-([^ ]+)(i[^ ]+)(\d\d)\s/);
    if (match) {
        $(".img." + match[1] + match[2]).show();
        $("h1." + match[1] + match[2] + match[3]).show();
    }
    divForm[0].animate({"top": "+=557px"}, 500, function(){
        $(this).animate({"top": "-=20px"}, 200);
    }); 
});

如果我们看到实际的HTML并了解整体问题,您可以通过更改HTML的组织方式或使用的类或通过在某些元素上添加自定义属性来简化这一过程。但是,这需要我们看到你正在做的更多,而不仅仅是重写一段代码。

答案 2 :(得分:1)

创建对象的对象地图:

IE:

var map = {
  "uli48": {
          img: "i4",
          h1: "uli48"
        }
}

然后你可以循环

var cls, classList = $(this).attr("class").split(" ");

for(var i=0; i<classList.length; i++) {
   cls = classList[i];
   if(map[cls]) {
      $("h1"+cls.h1).show();
      $("img"+cls.img).show();
    }
}

答案 3 :(得分:1)

让我们假设提到的类是独占的。如果您依赖于if语句的顺序,则需要进行一些调整。

首先,构建this类的字典及相关类:

var relatedImgs = { "tmi48" : "i4", ... };

这可以使用代码中的sed或编辑器宏来完成。 然后,您需要找出this的类:

var thisClasses = $(this).attr('class').split(' ');

然后尝试找到relatedImgs字典中的类并使用相关信息:

function findRelated(element) {
    var thisClasses = $(element).attr('class').split(' ');
    for (var i in thisClasses) {
        var imgClass = relatedImgs[thisClasses[i]];
        if (imgClass) {
            return [$("h1." + thisClasses[i]), 
                    $("img." + imgClass)];
        }
    }
    return null;
}

var related = findRelated(this);
if (related !== null) {
    for (var i in related) {
        related.show();
    }
}

答案 4 :(得分:0)

这个答案是以下答案的延伸:https://stackoverflow.com/a/20926579/1636522

因此,为了防止正则表达式随着需求的发展而越来越多(换句话说,为了保持可读性和可维护性),您可以将其拆分为更小的正则表达式,每个正则表达式与特定设备类别匹配。这会产生接近the class list solution的内容,但列表会缩减为几种模式:

var patterns = [
    '(i\\d[a-z]?)\\d\\d?', // iPhone
    '(sgs\\d)',            // Samsung Galaxy S
    '(bbz\\d\\d?)'         // Blackberry Z
];

var i = -1;
while (++i < patterns.length) {
    patterns[i] = new RegExp(
        '(?:^| )((?:tm|att|vz|ul)' + patterns[i] + ')(?: |$)'
    );
}

您也可以手动输入列表:

var patterns = [
    /(?:^| )((?:tm|att|vz|ul)(i\d[a-z]?)\d\d?)(?: |$)/,
    /(?:^| )((?:tm|att|vz|ul)(sgs\d))(?: |$)/,
    /(?:^| )((?:tm|att|vz|ul)(bbz\d\d?))(?: |$)/
];

按如下方式初始化click事件:

$('a').click(function () {
    var cls = $(this).attr('class'),
        i = -1, 
        m;
    while (++i < patterns.length) {
        if (m = cls.match(patterns[i])) {
            $('img.' + m[2]).show();
            $('h1.' + m[1]).show();
            break;
        }
    }
});

以下是演示:http://jsfiddle.net/wared/UTe5F/