如何在JavaScript中添加和删除事件监听器

3
new_line=function()
{
    var conteiner=document.createElement('div');
    conteiner.classList.add('conteiner');
    conteiner.addEventListener('click', function (event){on_click(event, conteiner);}, false);//this is an anonymous function so it is always new
    document.body.appendChild(conteiner);
    create_el(conteiner);
};

我有一个函数,并在其中使用addEventListener。我知道当我给出以下内容时:function (event){on_click(event, conteiner);} 我无法删除此EventListener,但我需要给on_click函数第二个参数。
delete_conteiner=function(which)
{
    which.removeEventListener("click", function (event){on_click(event, conteiner);}, false);//this isn't working
    document.body.removeChild(which);
};

是否可以添加一个执行on_click的EventListener,然后在另一个EventListener中删除它?以下是完整代码:

(function()
{
    var create_ul, user_names, menage_ul, open, look_for, save_as, user_name, real_name, on_click, set_up, create_el, show_hide_btn_click, delete_el, on_load, get_object_to_save, change_all, save, delete_conteiner, change_see_able, restart, new_line, new_cubes, scroll_with_ctrl;

    create_el=function(where, options)
    {
        var configs=options || {
            class_names:'textbox',
            value:''
        };
        var block=document.createElement('textarea');
        block.className=configs.class_names;
        block.value=configs.value;
        where.appendChild(block);
    };

    delete_el=function(where, which)
    {
        where.removeChild(which);
    };

    delete_conteiner=function(which)
    {
        which.removeEventListener("click", function(event){on_click(event, conteiner);}, false);//I know that won't work
        document.body.removeChild(which);
    };

    change_see_able=function(where)
    {
        var is_see_able=true;
        where.classList.forEach(function(str){
            if(str=='none_see_able')
            {
                is_see_able=false;
            }
        });
        if(is_see_able)
        {
            where.classList.add('none_see_able');
        }
        else
        {
            where.classList.remove('none_see_able');
        }
    };

    on_click=function(ev, conteiner)
    {
        var is_box_cliked=false;
        ev.target.classList.forEach(function(className){
            if(className=='textbox')
            {
                is_box_cliked=true;
            }
        });
        if(is_box_cliked)
        {
            if(ev.shiftKey)
            {
                if(!ev.ctrlKey)
                {
                    if(!ev.altKey)
                    {
                        create_el(conteiner);
                    }
                }
            }
            else if(ev.ctrlKey)
            {
                if(!ev.altKey)
                {
                    delete_el(conteiner, ev.target);
                }
            }
            else if(ev.altKey)
            {
                change_see_able(ev.target);
            }
            else
            {}
        }
        else
        {
            if(ev.ctrlKey)
            {
                delete_conteiner(conteiner);
            }
            else
            {
                if((conteiner.querySelector('.textbox')==null) || ev.shiftKey)
                {
                    create_el(conteiner);
                }
            }
        }
    };

    get_object_to_save=function()
    {
        var conteiners=document.body.querySelectorAll('.conteiner'), conteiners_to_save=Array();
        conteiners.forEach(function(textboxes){
            var textboxes=textboxes.querySelectorAll('.textbox'), textboxes_to_save=Array();
            textboxes.forEach(function(textbox){
                var textbox_to_save={
                    class_names:textbox.className,
                    value:textbox.value
                };
                textboxes_to_save.push(textbox_to_save);
            });
            conteiners_to_save.push(textboxes_to_save);
        });
        return [user_name, JSON.stringify(conteiners_to_save)];
    };

    new_line=function()
    {
        var conteiner=document.createElement('div');
        conteiner.classList.add('conteiner');
        create_el(conteiner);
        conteiner.addEventListener('click', function(event){on_click(event, conteiner);}, false);
        document.body.appendChild(conteiner);
    };

    load=function(conteiners)
    {
        if(conteiners.length===0)
        {
            new_line();
        }
        else
        {
            conteiners.forEach(function(textboxes){
                var conteiner=document.createElement('div');
                conteiner.classList.add('conteiner');
                conteiner.addEventListener('click', function(event){
                    on_click(event, conteiner);
                }, false);
                document.body.appendChild(conteiner);
                textboxes.forEach(function(options_for_textbox){
                    create_el(conteiner, options_for_textbox);
                });
            });
        }
    }

    save=function()
    {
        localStorage.setItem(real_name, JSON.stringify(get_object_to_save()));
    };

    look_for=function()
    {
        for(i=localStorage.length-1; i>=0; i--)
        {
            if(localStorage.key(i)!='name_last')
            {
                if(user_name===JSON.parse(localStorage.getItem(localStorage.key(i)))[0])
                {
                    return [true, localStorage.key(i)];
                }
            }
        }
        user_names.push(user_name);
        localStorage.setItem('names', JSON.stringify(user_names));
        return [false, 'c_'+new Date().getTime()];
    };

    open=function()
    {
        if(document.querySelector('.buttons > .open > input').value!='')
        {
            var conteiners=document.querySelectorAll('.conteiner');
            conteiners.forEach(function(conteiner)
            {
                delete_conteiner(conteiner);
            });
            user_name=document.querySelector('.buttons > .open > input').value;
            document.querySelector('.buttons > .open > input').value='';
            var is=look_for();
            real_name=is[1];
            localStorage.setItem('name_last', real_name);
            if(!is[0])
            {
                localStorage.setItem(real_name, JSON.stringify([user_name, JSON.stringify(new Array())]));
            }
            conteiners=JSON.parse(JSON.parse(localStorage.getItem(real_name))[1]);
            load(conteiners);
        }
    };

    save_as=function()
    {
        if(document.querySelector('.buttons > .save_as > input').value!='')
        {
            user_name=document.querySelector('.buttons > .save_as > input').value;
            document.querySelector('.buttons > .save_as > input').value='';
            real_name=look_for();
            localStorage.setItem('name_last', real_name);
            localStorage.setItem(real_name, JSON.stringify(get_object_to_save()));
        }
    };

    on_load=function()
    {
        var name=localStorage.getItem('name_last');
        if(localStorage.length===0)
        {
            user_names=new Array();
            localStorage.setItem('names', JSON.stringify(new Array()));
            user_name='first';
            real_name=look_for()[1];
            localStorage.setItem('name_last', real_name);
            localStorage.setItem(real_name, JSON.stringify([user_name, JSON.stringify(new Array())]));
        }
        else
        {
            real_name=name;
            user_name=JSON.parse(localStorage.getItem(real_name))[0];
            user_names=JSON.parse(localStorage.getItem('names'));
        }
        var conteiners=JSON.parse(JSON.parse(localStorage.getItem(real_name))[1]);
        load(conteiners);
    };

    new_cubes=function()
    {
        var conteiners=document.querySelectorAll('.conteiner');
        conteiners.forEach(function(conteiner){
            create_el(conteiner);
        });
    };

    restart=function()
    {
        var conteiners=document.querySelectorAll('.conteiner');
        conteiners.forEach(function(conteiner){
            delete_conteiner(conteiner);
        });
        new_line();
    };

    change_all=function()
    {
        var value=document.querySelector('.buttons > .to_all > textarea').value;
        document.querySelector('.buttons > .to_all > textarea').value='';
        var textboxes=document.querySelectorAll('.textbox');
        textboxes.forEach(function(textbox){
            textbox.value=value;
        });
    };

    set_size=function()
    {
        //textareas in menu prepare for calculations
        var textareas=document.querySelectorAll('label textarea');
        textareas.forEach(function(textarea){
            textarea.style.height='0px';
        });
        //inputs in menu prepare for calculations
        var inputs=document.querySelectorAll('label input');
        inputs.forEach(function(input){
            input.style.height='0px';
        });
        //show_hide_btn prepare for calculations
        var show_hide_btn=document.querySelector('.button.show_hide_menu');
        show_hide_btn.style.height='0px';
        //get height for textareas and inputs
        var width=textareas[0].offsetWidth+'px';
        var height=document.querySelector('.to_all .to_all').offsetHeight+'px';
        var uls=document.querySelectorAll('label ul');
        uls.forEach(function(ul){
            ul.style.bottom=height;
        });
        //textareas set height
        textareas.forEach(function(textarea){
            textarea.style.height=height;
        });
        //inputs set height
        inputs.forEach(function(input){
            input.style.height=height;
            input.style.width=width;
        });
        //show_hide_btn set height
        show_hide_btn.style.height=document.querySelector('.buttons_place').offsetHeight+'px';
    };

    show_hide_btn_click=function(btn)
    {
        if(btn.style.transform==='')
        {
            document.querySelector('.buttons_place').style.transform='translateX('+document.querySelector('.buttons').offsetWidth+'px)'
            btn.style.transform='rotateY(180deg)';
            setTimeout(function()
            {
                btn.style.borderTopLeftRadius='0';
                btn.style.borderBottomLeftRadius='0';
                btn.style.borderTopRightRadius='10px';
                btn.style.borderBottomRightRadius='10px';
            }, 750);
        }
        else
        {
            document.querySelector('.buttons_place').style.transform='';
            btn.style.transform='';
            setTimeout(function()
            {
                btn.style.borderTopLeftRadius='';
                btn.style.borderBottomLeftRadius='';
                btn.style.borderTopRightRadius='';
                btn.style.borderBottomRightRadius='';
            }, 750);
        }
    };

    ul_click=function(where, value)
    {
        where.querySelector('input').value=value;
    };

    create_ul=function(where, names_to_show)
    {
        var ul=where.querySelectorAll('ul');
        if(ul!=null)
        {
            ul.forEach(function(ul_one_object)
            {
                where.removeChild(ul_one_object);
            });
        }
        if(names_to_show.length!=0)
        {
            ul=document.createElement('ul');
            names_to_show.forEach(function(name)
            {
                var li=document.createElement('li');
                li.textContent=name;
                ul.appendChild(li);
            });
            ul.addEventListener('click', function(ev){ul_click(where, ev.target.textContent);}, false);
            ul.style.bottom=document.querySelector('.to_all .to_all').offsetHeight+'px';
            where.appendChild(ul);
        }
    };

    menage_ul=function(label, value)
    {
        var names_to_show=user_names.filter(function(name){
            return name.indexOf(value)==0;
        });
        create_ul(label, names_to_show)
    };

    set_up=function()
    {
        var show_hide_btn=document.querySelector('.button.show_hide_menu');
        show_hide_btn.addEventListener('click', function(event){show_hide_btn_click(show_hide_btn);}, false);
        var width=document.body.offsetWidth;
        setInterval(function()
        {
            if(width!=document.body.offsetWidth)
            {
                width=document.body.offsetWidth;
                set_size();
            }
        }, 500);
        set_size();
        var add_new_line_btn=document.querySelector('.new_line');
        add_new_line_btn.addEventListener('click', new_line, false);
        var add_new_cubes_btn=document.querySelector('.new_cubes');
        add_new_cubes_btn.addEventListener('click', new_cubes, false);
        var restart_btn=document.querySelector('.restart');
        restart_btn.addEventListener('click', restart, false);
        var save_structure_btn=document.querySelector('.save');
        save_structure_btn.addEventListener('click', save, false);
        var to_all_btn=document.querySelector('.to_all .to_all');
        to_all_btn.addEventListener('click', change_all, false);
        var save_as_btn=document.querySelector('.save_as .save_as');
        save_as_btn.addEventListener('click', save_as, false);
        var open_btn=document.querySelector('.open .open');
        open_btn.addEventListener('click', open, false);
        var labels=document.querySelectorAll('label');
        labels.forEach(function(label)
        {
            var input=label.querySelector('input');
            if(input!=null)
            {
                input.addEventListener('keyup', function(ev){menage_ul(label, input.value);}, false);
            }
        });
        on_load();
    };

    set_up();
})();

你可以使用 DOMelement.removeEventListener() 来实现,参见这里 https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/removeEventListener - Carsten Massmann
我喜欢这个问题在不到15分钟内就得到了5个答案,以不同的方式解释相同的内容。 - ippi
4个回答

1
removeEventListener() 方法用于移除使用 addEventListener() 方法添加的事件处理程序。 注意 若要移除事件处理程序,必须使用 addEventListener() 方法指定外部函数,如下面的示例中的 click_event_func。
匿名函数,如 "function (event){on_click(event, conteiner);}" 将不起作用。
click_event_func = function(event) {
  on_click(event, conteiner);
};

new_line = function() {
  var conteiner = document.createElement('div');
  conteiner.classList.add('conteiner');
  conteiner.addEventListener('click', click_event_func, false);
  document.body.appendChild(conteiner);
  create_el(conteiner);
};

delete_conteiner = function(which) {
  which.removeEventListener("click", click_event_func, false); 
  document.body.removeChild(which);
};

@Zlog 是的,匿名函数每次都会创建一个新的函数,所以它无法确定要删除哪个函数,因为每次都是新的函数。 - Vivek
哪个变量是我得到一个容器的变量(这很难解释,请转到链接> [link](http://projekton.nazwa.pl/testing/)) - Zlog
要删除事件处理程序,使用addEventListener()方法指定的函数必须是外部函数,就像下面的示例(click_event_func)一样。'外部函数'是什么意思?您只需要在addEventListener和removeEventListener中传递相同的引用即可。 - jannis
那么,如果容器不是全局的,你能告诉我在哪里需要实现这个函数吗? - Zlog
@Zlog 在这种情况下,您需要将“conteiner”与“click_event_func”绑定,并将其作为函数参数使用。 - Vivek
@Vivek 感谢您的帮助,问题已解决。我在 on_click 中写了 var container=this,在 new_line 中写了 addEventListener('click', on_click, false); 并删除了其中的参数:on_click=function(ev){...} - Zlog

0

我认为你的问题在于你没有使用命名函数。

尝试像这样做:

function NameHere(event) { on_click(event, conteiner); }

new_line=function() {
    var conteiner=document.createElement('div');
    conteiner.classList.add('conteiner');
    conteiner.addEventListener('click', NameHere, false);
    document.body.appendChild(conteiner);
    create_el(conteiner);
};

delete_conteiner=function(which) {
    which.removeEventListener("click", NameHere, false);//this isn't working
    document.body.removeChild(which);
};

问题在于,如果您不使用名称尝试删除侦听器,则会从之前添加的函数中删除不同的函数。

是的,如果container是全局变量,那么这是正确的,但它不是。 - Zlog
你可以简单地添加第二个参数并传递它。我的只是一个例子,用来解释问题。 - Loris
你能告诉我如何添加下一个参数吗?因为我已经尝试过这个:NameHere(event, container) - Zlog
但是这只在实现时执行了一次函数 :( - Zlog
如果您执行以下代码:_.addEventListener('click', NameHere(null,conteiner), false);_ 和 _function NameHere(event,element)_,则可以将DOM元素传递到函数中。 - Loris
显示剩余2条评论

0

例如:

which.removeEventListener("click", function (event){on_click(event, conteiner);}, false);
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                   // This here creates a new function. It's not related to
                                   // the function you created with addEventListener earlier.
                                   // Trying to remove it from eventlisteners on "which" is silly
                                   // because it doesn't exist there.

改为:

var eventHandler = function(event){on_click(event, conteiner);}; // Store for later
conteiner.addEventListener('click', eventHandler);               // Add.
conteiner.removeEventListener('click', eventHandler);            // Remove. 

只要引用相同的函数,就可以删除事件监听器。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接