如何在javascript中重构切换以获得更清晰的代码?

时间:2013-07-17 17:58:59

标签: javascript jquery refactoring

我正在尝试编写一些更清晰的Javascript / jQuery代码。如何将此功能重构为更清晰,更小的功能。绝对看起来有更好的方法来做到这一点。它有效,但我确信有更好的方法来编写这样的函数。提前谢谢!

function filterForm(purpose, entry) {
    switch (purpose) {
        case 'Business' : 
            switch (entry) {
                case 'Single': 
                    $("#moreq1").css( "display", "block" );   
                    $("#moreq2").css( "display", "none"  );   
                    $("#moreq3").css( "display", "none"  );  

                    break;
                case 'Double': 
                    $("#moreq1").css( "display", "block" );   
                    $("#moreq2").css( "display", "none"  );   
                    $("#moreq3").css( "display", "none"  );  

                    break;
                case 'Multiple' : 
                    $("#moreq1").css( "display", "block" );   
                    $("#moreq2").css( "display", "block" );   
                    $("#moreq3").css( "display", "none"  );  

                    break;
                }

                break;
            case 'Private' : 
                switch (entry) {
                    case 'Single'   : 
                        $("#moreq1").css( "display", "block" );   
                        $("#moreq2").css( "display", "none"  );   
                        $("#moreq3").css( "display", "none"  );  

                        break;
                    case 'Double'   : 
                        $("#moreq1").css( "display", "none"  );   
                        $("#moreq2").css( "display", "none"  );   
                        $("#moreq3").css( "display", "none"  );  

                        break;
                    case 'Multiple' : 
                        $("#moreq1").css( "display", "none"  );   
                        $("#moreq2").css( "display", "none"  );   
                       $("#moreq3").css( "display", "none"  );  

                        break;
                }   

                break;
            case 'Tourist' : 
                switch (entry) {
                    case 'Single'   : 
                        $("#moreq1").css( "display", "block" );   
                        $("#moreq2").css( "display", "none"  );   
                        $("#moreq3").css( "display", "block"  );  

                        break;
                    case 'Double'   : 
                        $("#moreq1").css( "display", "none" );   
                        $("#moreq2").css( "display", "none"  );   
                        $("#moreq3").css( "display", "none"  );  

                        break;
                    case 'Multiple' : 
                        $("#moreq1").css( "display", "none"  );   
                        $("#moreq2").css( "display", "none" );   
                        $("#moreq3").css( "display", "none" );  

                        break;
                }       

                break;
            }
    }
}

7 个答案:

答案 0 :(得分:1)

在查看了所有条件后,似乎可以归结为:

function filterForm(purpose, entry) {
    var q1 = purpose == 'Business' || entry == 'Single' ? 'block' : 'none';
    var q2 = purpose == 'Business' && entry == 'Multiple' ? 'block' : 'none';
    var q3 = purpose == 'Tourist' && entry == 'Single' ? 'block' : 'none';

    $("#moreq1").css( "display", q1 );   
    $("#moreq2").css( "display", q2 );   
    $("#moreq3").css( "display", q3 ); 
}

答案 1 :(得分:1)

我首先删除所有隐藏语句 - 只是隐藏所有隐藏语句,然后只显示那些需要的语句(此处包含if - 语句,请参阅@nmynarcik's answer以获取{{{{3}}的中间步骤1}} ES):

switch

可以进一步简化为

function filterForm(purpose, entry) {
    $("#moreq1, #moreq2, #moreq3").css("display", "none");

    if (purpose == 'Business') {
        $("#moreq1").css("display", "block");
        if (entry == 'Multiple')
            $("#moreq2").css("display", "block");
    } else if (purpose == 'Private' && entry == 'Single')
         $("#moreq1").css("display", "block");
    } else if (purpose == 'Tourist' && entry == 'Single') {
         $("#moreq1, #moreq3").css("display", "block");
    }
}

如果它变得越来越复杂,我建议使用单个显示值的查找映射,而不是使用带有重复语句的function filterForm(purpose, entry) { $("#moreq1, #moreq2, #moreq3").css("display", "none"); if (purpose == 'Business' || entry == 'Single') $("#moreq1").css("display", "block"); if (purpose == 'Business' && entry == 'Multiple') $("#moreq2").css("display", "block"); if (purpose == 'Tourist' && entry == 'Single') $("#moreq3").css("display", "block"); } 语句。对于您的设置,它看起来像

switch

当然,如果更短,您可以更换var show = { "moreq1": { "Business": true, "Private": { "Single": true }, "Tourist": { "Single": true } }, "moreq2": { "Business": { "Multiple": true } }, "moreq3": { "Tourist": { "Single": true } } }; for (var id in show) { var l = show[id]; $("#"+id).css("display", l[purpose] === true || l[purpose] && l[purpose][entry] ? "block" : "none"); } purpose的顺序。

答案 2 :(得分:1)

虽然其他答案在组合各种可能性方面做得不错,但使用所有可能性的“地图”似乎更合乎逻辑,并参考:

var filterForm = (function () {
    var moreq = [
        "",        // So you can use indexes starting at 1
        "moreq1",
        "moreq2",
        "moreq3"
    ], Purposes = {
        "Business": {
            "Single": [moreq[1]],
            "Double": [moreq[1]],
            "Multiple": [moreq[1], moreq[2]]
        },
        "Private": {
            "Single": [moreq[1]],
            "Double": [],
            "Multiple": []
        },
        "Tourist": {
            "Single": [moreq[1], moreq[],
            "Double": [],
            "Multiple": []
        }
    };

    return function (purpose, entry) {
        var i, j, cur, display;

        for (i = 1, j = moreq.length; i < j; i++) {
            cur = moreq[i];
            display = Purposes[purpose][entry].indexOf(cur) > -1 ? "block" : "none";
            console.log("Setting " + cur + " as " + display);
            //$("#" + cur).css("display", display);
        }
    };
}());

filterForm("Business", "Multiple");

DEMO: http://jsfiddle.net/w3Jnn/1/

对象中的数组是将显示设置为block的元素。只要您想要更改特定设置,只需修改Purposes对象的数组。

当然,我的函数没有对Purposes[purpose][entry].indexOf(cur) > -1部分进行太多检查 - 它假定purposeentry参数将具有有效值。这可以修改以检查,但现在看起来并不重要。

作为一个注释,它使用一个闭包(周围的(function () { }))来实例化Purposesitems变量一次,但是将它们排除在全局范围之外。

另请注意,并非所有浏览器(主要是旧版IE)都支持Array.indexOf方法,因此在https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Compatibility上有一个垫片可以包含在您的页面上以确保其有效,以及其他你可以在谷歌找到。

答案 3 :(得分:1)

我不确定我有多喜欢这种方式,但这是一种非切换,非如此方式。它也可以帮助进行测试,因为您可以单独测试 lookup

但是,如果目的条目不是查找中的键,那么您将会抛出一些错误。

function filterForm(purpose, entry) {
    var lookup = {}
    lookup['Business'] = {'Single':{'q1':'block','q2':'none','q3':'none'},
                         {'Double':{'q1':'block','q2':'none','q3':'none'}};

    lookup['Private'] = {...etc...};

    $('#moreq1').css('display', lookup[purpose][entry]['q1]);
}

答案 4 :(得分:0)

如果你想坚持使用切换,给他们所有的类,你可以设置所有显示:无;当你开始你的方法。

然后做:

function filterForm(purpose, entry) {

   $('.qItem').hide();

    switch (purpose) {

        case 'Business' : 

            $("#moreq1").css( "display", "block" );

            switch (entry) {

                case 'Multiple' : 

                    $("#moreq2").css( "display", "block" );

                break;

            }

        break;

        case 'Private' : 

            switch (entry) {

                case 'Single'   : 

                    $("#moreq1").css( "display", "block" );   
                    break;

            }   

        break;

        case 'Tourist' : 

            switch (entry) {

                case 'Single'   : 

                    $("#moreq1").css( "display", "block" );   
                    $("#moreq3").css( "display", "block"  );  

                break;

            }       

        break;

    }

}

您可以在此处查看该课程的使用方式:http://jsfiddle.net/pMfgy/

答案 5 :(得分:0)

试试这个:

function filterForm(purpose, entry) {
    var hideMap = {
        Business: {
            Single: [2, 3],
            Double: [2, 3],
            Multiple: [3]
        },
        Private: {
            Single: [2, 3],
            Double: [1, 2, 3],
            Multiple: [1, 2, 3]
        },
        Tourist: {
            Single: [2],
            Double: [1, 2, 3],
            Multiple: [1, 2, 3]
        }
    };

    hideShow(hideMap[purpose][entry]);
}

function hideShow(a) {
    var allEls = '#moreq1, #moreq2, #moreq3';
    for (var i = 0; i < a.length; i++) {
        a[i] = '#moreq' + a[i];
    }
    var hideEls = a.join(',');
    $(hideEls).hide(a.join());
    $(allEls).not(hideEls).show();
}

<强> jsFiddle

答案 6 :(得分:0)

正如很多人所说,看起来就像你可以大大简化显示逻辑一样,但如果根据moreq1维持不同的状态很重要,基于moreq2moreq3变量值的purposeentry元素,我建议您将显示“逻辑”的大部分转移到CSS,而不是JS / jQuery。 。

大多数逻辑可以替换为与purposeentry值绑定的CSS样式定义:

<强> CSS

// "Business" display styles
// "Business - Single" display styles
.business.single #moreq1 {display: block}
.business.single #moreq2,
.business.single #moreq3 {display: none}

// "Business - Double" display styles
.business.double #moreq1 {display: block}
.business.double #moreq2,
.business.double #moreq3 {display: none}

// "Business - Multiple" display styles
.business.multiple #moreq1,
.business.multiple #moreq2 {display: block}
.business.multiple #moreq3 {display: none}

// "Private" display styles
// "Private - Single" display styles
.private.single #moreq1 {display: block}
.private.single #moreq2,
.private.single #moreq3 {display: none}

// "Private - Double" display styles
.private.double #moreq1,
.private.double #moreq2,
.private.double #moreq3 {display: none}

// "Private - Multiple" display styles
.private.multiple #moreq1,
.private.multiple #moreq2,
.private.multiple #moreq3 {display: none}

// "Tourist" display styles
// "Tourist - Single" display styles
.tourist.single #moreq1,
.tourist.single #moreq3 {display: block}
.tourist.single #moreq2 {display: none}

// "Tourist - Double" display styles
.tourist.double #moreq1,
.tourist.double #moreq2,
.tourist.double #moreq3 {display: none}

// "Tourist - Multiple" display styles
.tourist.multiple #moreq1,
.tourist.multiple #moreq2,
.tourist.multiple #moreq3 {display: none}

之后,您可以使用<body>purpose值,使用jQuery将样式简单地分配给父容器(甚至是entry标记):

<强> JS

function filterForm(purpose, entry) {
    var dynamicClasses = purpose + " " + entry;
    $("#parent_element_ID").addClass(dynamicClasses.toLowerCase());
}

此时,CSS将接管并根据您的CSS规则显示/显示元素。

虽然它可能看起来像很多CSS,但它不仅使用CSS作为预期目的,而且还进行任何更改(或添加新部分),简单的CSS更新,而不是JS代码更改。