1

我刚刚进入我的 javascript(模式、命名空间、对象等),并试图在我的最新项目中实践其中的一些。

我有一个简单的表单,我正在尝试根据选中的复选框来显示/隐藏某些内容。HTML 无法更改(长篇大论),所以我只关注手头的 javascript 问题,也就是说,当 ID 不止一个时,我怎样才能很好地减少重复性?

脚本(我确定可以压缩)如下:

var prereg = {

    hideItems: (function() {
        document.getElementById('companyName-element').style.display = 'none';
        document.getElementById('companyName-label').style.display = 'none';
    })(),

    showItems: function() {
        var checkbox = document.getElementById('businessCustomer'); 
        if(checkbox.checked) {
            document.getElementById('companyName-element').style.display = 'block';
            document.getElementById('companyName-label').style.display = 'block';
        } else {
            document.getElementById('companyName-element').style.display = 'none';
            document.getElementById('companyName-label').style.display = 'none';
        }
    },

    addEvent: function (el, ev, fn) {
         if (el.addEventListener) {
             el.addEventListener(ev, fn, false);
         } else if (el.attachEvent) {
             el.attachEvent('on' + ev, fn);
         } else {
             el['on' + ev] = fn;
         }
     }

}

prereg.addEvent(document.getElementById('businessCustomer-label'), 'click', prereg.showItems);
prereg.addEvent(document.getElementById('businessCustomer-element'), 'click', prereg.showItems);
4

2 回答 2

1

我认为您正在寻找事件委托,这是一种奇特的说法,即对同一类型的所有事件使用单个处理程序。好吧,即使是不同的类型也是一种选择。但只是一个例子:

假设您的 html 如下所示:

<form id="formId"><input type="checkbox" id="foo"/>
    <input type="checkbox" id="bar"/>

等等(不能被打扰)。您的 JS 可以使用 1 个事件侦听器和处理程序处理所有点击事件:

var form = document.getElementById('formId');
if (form.addEventListener)
{
    form.addEventListener('click',clickDelegator,false);
}
else
{
    form.attachEvent('onclick',clickDelegator);
}
function clickDelegator(e)
{
    e = e || window.event;
    var target = e.target || e.srcElement;//target holds reference to clicked element
    if (target.tagName.toLowerCase() !== 'input')
    {
        //not interested in this, just let the event pass
        return e;// or return true; or return;... doesn't matter
    }
    switch(target.type.toLowerCase())//target is an input field, we've established that
    {
        case 'checkbox':
            //code for checkboxes;
            //target is a checkbox, use target.checked, target.id, as normal
        break;
        case 'button':
            //deal with buttons here
        break;
        //etc...
    }
}

如果您希望 1 个委托函数来处理所有事件,则可以,但随后您将不得不使用switch...caseall e.type,当然这通常会导致无用、无法维护的蒙特函数。但你知道:这可能的。

需要关闭吗?好没问题:

form.addEventListener('click',(function(someVar)
{
    return function(e)
    {
        e = e || window.event;
        clickDelegator.apply(this,[e,someVar]);
        //pass as argument, the clickDelegator was declared outside closure scope
        //and doesn't have access to someVar, but this way, it has the closure var
        //as an argument
    }
})(theClosureVar),false);

谷歌一些事件委托的更多例子,你不会后悔的……这是 JavaScript 的那些被严重低估的特性之一,并且没有像他们应该的那样广为人知。我希望我能给你一个更好的闭包-委托组合的例子,因为这是一个非常强大的组合。以移动设备为例:没有点击事件,只有 touchstart 和 touchend 事件。因此,您将 touchstart 处理程序设置为绑定 touchend 侦听器,并通过闭包将超时 id 添加到 touchend 事件的处理程序。如果一段时间过去了,用户可能没有点击该元素,而是使用了他/她手机的其他一些触摸功能,因此您可以分离监听器。

我不擅长解释这一点,但看一些自定义tab事件如何工作的例子,它通常归结为类似于我在这里运球的东西,现在我要睡觉了......祝你好运

于 2012-08-13T15:54:24.803 回答
0

无需过多地重构代码,您只需将要操作的对象缓存在一个数组中并在循环中处理它们。

var prereg = (function () {

    // add your style elements to this array. We only call getElementId once
    // and not on each function call.
    var styleObjects = [ 
            document.getElementById('companyName-element'),
            document.getElementById('companyName-label')
        ],

        checkbox = document.getElementById('businessCustomer'),

        i;

    // Function applies display style to all elements in styleObjects array
    function applyStyle(display) {
        var i;
        for (i = 0; i < styleObjects.length; i += 1) {
            styleObjects[i].style.display = display;
        }
    }

    function hideItems() {
        applyStyle('none');
    }

    function showItems() {            
        if(checkbox.checked) {
            applyStyle('block');
        } else {
            applyStyle('none');
        }
    }

    function addEvent(el, ev, fn) {
        if (el.addEventListener) {
         el.addEventListener(ev, fn, false);
        } else if (el.attachEvent) {
         el.attachEvent('on' + ev, fn);
        } else {
         el['on' + ev] = fn;
        }
    }    

    // Attach event handler to all objects in styleObjects array
    for (i = 0; i < styleObjects.length; i += 1) {
        addEvent(styleObjects[i], 'click', showItems);
    }

    return {
        hideItems: hideItems,
        showItems: showItems,
        addEvent: addEvent
    };
}());

如果你想多次这样做,修改它以接受复选框和元素数组作为参数将是微不足道的。

于 2012-08-13T16:13:00.550 回答