简体   繁体   English

JavaScript AddEventListener仅触发一次

[英]Javascript AddEventListener Fires only once

I have the following HTML 我有以下HTML

...
    <div class="content-row"><div class="col-md-4"></div>
            <div class="col-md-4">
                <form>
                    <div id='undiv' class="form-group"><label for="uname">Name:</label><input id="uname" type="text" class="form-control"/></div>
                    <div class="form-group"><label for="email">Email (optional):</label><input id="email" type="text" class="form-control" /></div>
                    <div class="form-group"><label for="gamecode">Game Code:</label><input id="gamecode" type="text" class="form-control" /></div>
                    <div class="form-group pull-right"><input id="join" type="button" value="Join" class="btn btn-primary btn-lg btn btn-primary btn-lg" /></div>
                </form>
            </div><div class="col-md-4"></div>
    </div>
....

Javascript below the HTML in body body HTML下方的Javascript

<script type='text/javascript'>
            var uname = document.getElementById("uname");
            var email = document.getElementById("email");
            var gamecode = document.getElementById("gamecode");
            var joinbtn = document.getElementById("join");
            var notify = document.getElementById("notify");
            var undiv = document.getElementById("undiv");
...


    uname.addEventListener("blur",function(evt) {
                console.log('onblur');
                var un = uname.value;
                console.log(un);
                if(un.length >= 2) {
                    undiv.className += " has-success has-feedback";
                    undiv.innerHTML += '<span id="mark" class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>';
                }
                else {
                    undiv.className += " has-error has-feedback";
                    undiv.innerHTML += '<span id="mark" class="glyphicon glyphicon-remove form-control-feedback" aria-hidden="true"></span>';
                }
                //uname.value = un;
            });

            uname.addEventListener("focus",function(evt) {
                console.log('onfocus');
                undiv.className = "form-group";
                var mark = document.getElementById("mark");
                if(mark !=null) {
                    mark.parentNode.removeChild(mark);      
                    console.log("mark="+mark);  
                }   
            });
    </script>

The uname on onfocus and onblur events fire only once. unameonfocusonblur事件触发一次。

I have another eventListener on the button click event and it works fine. 我在button click event上有另一个eventListener ,它工作正常。

I don't understand why focus and blur eventListeners don't fire whenever the event happens ? 我不明白为什么每次事件发生时focusblur事件eventListeners都不会触发?

The debugger on Chrome and Firefox show no errors or warning... And I don't understand What is going wrong ? Chrome和Firefox上的调试器未显示任何错误或警告...而且我不明白这是怎么回事?

http://jsfiddle.net/ddf5h2nu/ http://jsfiddle.net/ddf5h2nu/

A good practice is to keep a ruler on your desk, and if you find yourself typing element.innerHTML += "..." , just grab the ruler and smack the back of your hand. 一个好的做法是将一把尺子放在桌子上,如果您发现自己输入element.innerHTML += "..." ,则只需抓住尺子并and一下手背即可。

;-) ;-)

Seriously though, using += after .innerHTML is very destructive and unnecessary and as you can see leads to unexpected results. 严重的是,在.innerHTML之后使用+=非常具有破坏性,并且不必要,并且可以看到导致意外结果的结果。

The other answer shows how to do it with DOM creation methods, which is a good way, but if you want to use HTML markup, then use .insertAdjacentHTML() instead of .innerHTML . 另一个答案显示了如何使用DOM创建方法来做到这一点,这是一个好方法,但是如果您要使用HTML标记,请使用.insertAdjacentHTML()而不是.innerHTML

uname.addEventListener("blur",function(evt) {
    console.log('onblur');
    var un = uname.value;
    console.log(un);
    if(un.length >= 2) {
        undiv.className += " has-success has-feedback";
        undiv.insertAdjacentHTML("beforeend", '<span id="mark" class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>');
    }
    else {
        undiv.className += " has-error has-feedback";
        undiv.insertAdjacentHTML("beforeend", '<span id="mark" class="glyphicon glyphicon-remove form-control-feedback" aria-hidden="true"></span>');
    }
    //uname.value = un;
});

You'll notice that the first argument is "beforeend" and the second is your HTML. 您会注意到第一个参数是"beforeend" ,第二个参数是您的HTML。 The .insertAdjacentHTML() method accepts four different strings as the first argument. .insertAdjacentHTML()方法接受四个不同的字符串作为第一个参数。 They are as follows: 它们如下:

  • "beforebegin" (put the markup before the element) "beforebegin" (将标记放在元素之前)
  • "afterbegin" (put the markup inside the element at the beginning) "afterbegin" (将标记放在元素的开头)
  • "beforeend" (put the markup inside the element at the end) "beforeend" (将标记放在元素的末尾)
  • "afterend" (put the markup after the element) "afterend" (将标记放在元素之后)

So there are four positions where the HTML can be inserted relative to the element on which the method is invoked. 因此,相对于调用该方法的元素,可以在四个位置插入HTML。 These don't destroy any existing elements, which is why it's better than .innerHTML . 这些不会破坏任何现有元素,这就是为什么它比.innerHTML更好的原因。

When you change undiv 's innerHTML attribute, you are causing the <input> element to be re-created from the HTML, thus losing the event listener. 更改undivinnerHTML属性时,将导致从HTML重新创建<input>元素,从而丢失事件侦听器。

This is a good alternative: 这是一个很好的选择:

var newItem = document.createElement('span');
newItem.id = 'mark';
newItem.className = 'glyphicon glyphicon-ok form-control-feedback';
newItem.setAttribute('aria-hidden', true);
undiv.appendChild(newItem);

Fiddle 小提琴

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM