【问题标题】:Javascript onclick firing 4 timesJavascript onclick 触发 4 次
【发布时间】:2018-09-21 12:52:17
【问题描述】:

如果密码错误,登录表单应该会显示警报。但是,它显示了 4 次警报。

id:'loginbutton' 的按钮在点击时触发函数'auth()'。 它适用于登录和注销。但是当我尝试使用错误的用户名,密码对时,警报消息 window.alert("Wrong username or password") 会一次又一次地显示四次。这意味着 onclick() 事件由于某种原因被触发了四次。

在这里,相同的登录按钮也可用作退出按钮。我正在使用函数 setLoginButton() 来确定用户的当前状态(登录与否)并据此更新按钮文本。

HTML:

<body onload = "setLoginButton()">
<nav class="navbar navbar-inverse navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Lorem</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <form class="navbar-form navbar-right">
            <div class="form-group">
              <input type="text" placeholder="Username" class="form-control" id="username">
            </div>
            <div class="form-group">
              <input type="password" placeholder="Password" class="form-control" id="password">
            </div>
            <button type="submit" class="btn btn-success" onclick="auth(event)" id="loginbutton">Sign in</button>
          </form>
        </div><!--/.navbar-collapse -->
      </div>
    </nav>

Javascript:

// Init datatables
$(document).ready( function () {
    $('#content1').DataTable();
    $('#holdTable').hide();
} );


function setLoginButton() {
    token = window.sessionStorage.getItem('cicitoken');
    if (token == null) {
        return false;
    }
    else {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 400) {
                window.sessionStorage.removeItem('cicitoken');
                buttonText = "Sign In";
                displayForm = "block";
            } 
            else {
                buttonText = "Sign Out";
                displayForm = "none";
            }
            document.getElementById("loginbutton").innerHTML = buttonText;
            document.getElementById("username").style.display = displayForm;
            document.getElementById("password").style.display = displayForm;
        };
        xhttp.open("POST", "/api-token-verify/", true);
        xhttp.setRequestHeader("Content-type", "application/json");
        xhttp.send(JSON.stringify({"token": token}));
    }
}


//auth function to get token and use sessionstorage
auth = function(e) {
    e.preventDefault();

    token = window.sessionStorage.getItem('cicitoken');
    if ( token != null) {
        window.sessionStorage.removeItem('cicitoken');
        location.reload()
    }
    else {
        var xhttp = new XMLHttpRequest();
        jdata={username:document.getElementById("username").value,password:document.getElementById("password").value};
        xhttp.onerror = function(xhr, status, err) {
            console.log(err);
        }
        xhttp.onabort = function(xhr, status, err) {
            console.log(err);
        }
        xhttp.onreadystatechange = function() {
            if (xhttp.readyState==4 && xhttp.status==200) {
                var response = JSON.parse(xhttp.responseText);
                window.sessionStorage.setItem('cicitoken',response.token);
            }
            else {
                window.alert("Wrong username or password");
                setLoginButton();
            }
            setLoginButton();
        }

        xhttp.open("POST", "/api-token-auth/", true);
        xhttp.setRequestHeader("Content-type", 'application/json; charset=UTF-8');
        xhttp.send(JSON.stringify(jdata));
    }
}

【问题讨论】:

  • 试试把type button和event.stopPropagation()

标签: javascript html onclick


【解决方案1】:

XMLHttpRequest 将遍历它们的就绪状态。 所以它从状态 0 开始,它会遍历每个状态,直到到达状态 4,完成。

由于您的警报与 onreadystatechange 事件相关联,因此该事件也将被调用 4 次:

xhttp.onreadystatechange = function() {
    if (xhttp.readyState==4 && xhttp.status==200) {
        var response = JSON.parse(xhttp.responseText);
        window.sessionStorage.setItem('cicitoken',response.token);
    }
    else {
        window.alert("Wrong username or password");
        setLoginButton();
    }            
    setLoginButton();
}

由于警报与条件相关联:if readyState !== 4,因此它将显示状态 0、1、2 和 3 的警报。

解决方案是将警报包含在某处的if readyState === 4 块中,而不是将其放在外面。然后,您还可以将警报绑定到 XMLHttpRequest 的 onerror 事件,以在 XMLHttpRequest 在达到 readyState 4 之前失败时捕获错误。

这也意味着您在其他 readystatechange 处理程序中所做的所有样式更改也会被调用太多次,而不是仅在请求结果已知时调用。

【讨论】:

    【解决方案2】:

    对于面临同样问题的任何人,这就是我根据@Shilly 的回答修改代码的方式:

        xhttp.onreadystatechange = function() {
            if (xhttp.readyState==4 && xhttp.status==200) {
                var response = JSON.parse(xhttp.responseText);
                window.sessionStorage.setItem('cicitoken',response.token);
                setLoginButton();
            }
            else if (xhttp.readyState==4 && xhttp.status==400){
                window.alert("Wrong username or password");
                setLoginButton();
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-14
      • 1970-01-01
      • 2022-09-03
      • 2013-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多