首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Javascript onclick触发4次

Javascript onclick触发4次
EN

Stack Overflow用户
提问于 2018-09-21 20:52:18
回答 2查看 90关注 0票数 1

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

id为‘loginbutton’的按钮触发函数'auth()‘onclick。它在登录和注销时工作正常。但是,当我尝试使用错误的用户名、密码对时,警报消息window.alert(“错误的用户名或密码”)会连续显示四次。这意味着onclick()事件由于某种原因被触发了四次。

在这里,同样的“登录”按钮也可以作为“退出”按钮。我使用函数setLoginButton()来确定用户的当前状态(是否登录),并基于此更新按钮文本。

HTML:

代码语言:javascript
复制
<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:

代码语言: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));
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-21 21:00:22

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

由于您的警报绑定到onreadystatechange事件,该事件也将被调用4次:

代码语言:javascript
复制
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处理程序中所做的所有样式更改也会被调用太多次,而不是仅当请求的结果已知时才调用。

票数 3
EN

Stack Overflow用户

发布于 2018-09-22 04:30:16

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

代码语言:javascript
复制
    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();
        }
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52444224

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档