代码之家  ›  专栏  ›  技术社区  ›  P. Nick

使用自定义DOM函数时,表单第二次使用PreventDefault重新加载页面

  •  0
  • P. Nick  · 技术社区  · 6 年前

    我有一个登录表单,提交时它调用这个函数

    login = (that) ->
      header =
        "X-CSRFToken": window.csrftoken
    
      $('body').toggleDOM('.loading', true)
    
      fermata.json("/login").post(header, that, (err, data) ->
        $('body').toggleDOM('.loading', false)
    
        if !data.success
          htAlert.error 'Incorrect username and/or password.'
      )
    

    这将在调用API时添加一个“加载微调器”,然后将其移除。这在你第一次提交表单时很有效,因为我正在使用 preventDefault 所以页面不会重新加载。不过,在第二次尝试时,页面将重新加载,我不知道为什么会出现这种情况。

    我的dom函数,用于向主体添加元素:

    $.fn.toggleDOM = (domName, b) ->
      dom = domName[domName.search(/([\.\#])/)]
      newDom = domName.substring(1)
    
      if dom == '#'
        if b
          document.body.innerHTML += '<div id="' + newDom + '"></div>'
        else
          document.getElementById(newDom).remove()
      else
        if b
          document.body.innerHTML += '<div class="' + newDom + '"></div>'
        else
          document.getElementsByClassName(newDom)[0].remove()
    

    表单提交事件:

    $ ->
      trigger = document.querySelectorAll("[data-trigger]")
    
      trigger.forEach((i) ->
         i.addEventListener "submit", (e) ->
          e.preventDefault()
          # We have to pass the event instead of the element.
          switch i.attributes["data-trigger"].nodeValue
            when "[form/login]" then login(e)
    

    HTML:

    <form data-trigger="[form/login]" class="login">
      <input type="hidden" class="uuid hidden">
      <input placeholder="Username" class="username">
      <input placeholder="Password" type="password" class="password">
      <button type="submit">Login</button>
    </form>
    

    我需要知道为什么它会在第二次尝试时重新加载页面。如果我移除 $('body').toggleDOM('.loading', true) 它的行为和预期不一样。

    另外,我是 使用jquery,我使用这个小库: https://github.com/finom/balalaika

    1 回复  |  直到 6 年前
        1
  •  1
  •   Henrik Andersson user2120121    6 年前

    问题在于如何将事件侦听器附加到元素上。 您要做的工作不适用于简单的JavaScript。

    您需要利用的是事件委托;它不会改变太多代码方面的内容,但会改变它的工作方式。

    通过移除for循环并将处理程序附加到 document 相反,你会得到你想要的。

    document.addEventListener "submit", (e) ->
      e.preventDefault();
      switch e.target.attributes["data-trigger"].nodeValue
        when "[form/login]" then login(e)
    

    有一篇很好的文章涵盖了 the how and why