2015-02-10 238 views
0

我有以下的HTML的Javascript的addEventListener只触发一次

... 
    <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的HTML低于body

<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> 

unameonfocusonblur事件触发一次。

我对button click event有另一个eventListener,它工作正常。

我不明白为什么focusblureventListeners在事件发生时不会触发?

在Chrome和Firefox上的调试器显示没有错误或警告......而我不明白什么是错的?

http://jsfiddle.net/ddf5h2nu/

+4

'uname'输入被你的onblur处理程序覆盖(删除并重新创建),因为你正在为其容器div设置'innerHTML'。 – nnnnnn 2015-02-10 21:13:38

回答

9

好的做法是保持一个标尺放在办公桌上,如果你发现自己打字element.innerHTML += "...",只是抓住标尺和咂了回来你的手。

;-)

虽然严重,使用+=.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; 
}); 

你会发现,第一个参数是"beforeend",第二个是你的HTML。方法.insertAdjacentHTML()接受四个不同的字符串作为第一个参数。它们分别是:

  • "beforebegin"(把标记元素之前)
  • "afterbegin"(把标记元素中开头)
  • "beforeend"(把标记内元素末尾)
  • "afterend"(把元素放在元素后面)

所以有四个位置可以插入相对于调用该方法的元素的HTML。这些不会破坏任何现有元素,这就是为什么它比.innerHTML更好。

+3

感谢您花时间解释详细信息。真的很感激它。下次我使用DOM时,我会记住你的建议。 – anu 2015-02-11 02:47:59

+1

这样一个令人惊讶的被低估的答案。花了我几个月的时间被错误的方向领导,终于在大量不正确的(和高度优先的)答案中找到了这一点。这比使用innerHTML,append,prepend等实现他们不打算用于的东西更加灵活。 insertAdjacentHTML()很棒。 – 2017-04-29 03:37:24

1

当您更改undivinnerHTML属性,你是导致<input>元素从HTML重新创建,从而失去了事件侦听器。

这是一个很好的选择:

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