1. 程式人生 > >Ajax點選提交按鈕時需要點選兩次的問題

Ajax點選提交按鈕時需要點選兩次的問題

主要原因:Ajax的非同步請求

原始碼:

//傳送網路請求登入介面
$.ajax({
    url: "./service/login.php",
    type: "POST",
    data: {
        username: $scope.username,
        password: $scope.password
    },
    success: function (data) {
        console.log(data);
        data = JSON.parse(data);
        if (data.code < 0){
            alert(data.message);
            return;
        }
        alert(data.message);
        $location.path('/home');
            },
    error: function (data) {
        console.log(data);
    }
});

方法一:Ajax非同步變同步(ajax預設是非同步請求)不推薦

使用非同步請求的好處是在發起請求時不影響使用者其他操作,而同步只有等到返回結果時才能繼續操作。

$.ajax({
    url: "./service/login.php",
    type: "POST",
    async:false,
    data: {
        username: $scope.username,
        password: $scope.password
    },
    success: function (data) {
        console.log(data);
        data = JSON.parse(data);
        if (data.code < 0){
            alert(data.message);
            return;
        }
        alert(data.message);
        $location.path('/home');
            },
    error: function (data) {
        console.log(data);
    }
});

方法一雖然可以但是控制檯報出警告,這種方法已經被廢棄。

方法二:在$location.path(" ")後面加上$scope.$apply()。

使用$scope.$apply()原因如下:

AngularJS對JS原生的非同步事件進行了封裝:

  • Events => ng-click
  • Timeouts => $timeout
  • jQuery.ajax() => $http

這是一個傳統的非同步函式,僅僅在最後呼叫了$scope.$apply() 來通知AngularJS非同步事件正在發生。

$scope.$apply()應該在儘可能接近非同步事件繫結的地方被呼叫。

$scope.$apply() should occur as close to the async event binding as possible.

不要隨意的在你的程式碼中使用它,如果你使用了if (!$scope.$$phase) $scope.$apply(),因為你沒有處在呼叫棧的高層。

儘可能使用AngularJS的服務來代替原始的JS。如果你在建立一個AngularJS服務(例如為套接字建立服務),你應該在觸發回撥的任何位置都使用$scope.$apply()

注:不知道翻譯的對不對,附上後兩段的原文:

Do NOT randomly sprinkle it throughout your code. If you are doing 
if (!$scope.$$phase) $scope.$apply() it’s because you are not high enough in the call stack.

Whenever possible, use AngularJS services instead of native. If you’re creating an AngularJS service (such as for sockets) it should have a $scope.$apply() anywhere it fires a callback.

修改後程式碼:

$.ajax({
    url: "./service/login.php",
    type: "POST",
    // async:false,
    data: {
        username: $scope.username,
        password: $scope.password
    },
    success: function (data) {
        console.log(data);
        data = JSON.parse(data);
        if (data.code < 0){
            alert(data.message);
            return;
        }
        alert(data.message);
        $location.path('/home');
        $scope.$apply();
            },
    error: function (data) {
        console.log(data);
    }
});

方法三:angularJS $http服務

原文地址:https://blog.csdn.net/sky_lunar_g/article/details/71093142?tdsourcetag=s_pcqq_aiomsg

        function doLoginNg() {
            $http({
                method: 'post',
                url: '../service/login.php',
                data: {username: $scope.username, password: $scope.password},
                headers: {'Content-Type': 'application/x-www-form-urlencoded'},
                transformRequest: function (obj) {
                    var str = [];
                    for (var p in obj) {
                        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
                    }
                    return str.join("&");
                }
            }).then(function successCallback(response) {
                console.log(response);
                data = response.data
                //判斷是否登入成功
                if (data.code < 0) {
                    alert(data.message);
                    return;
                }

                localStorage.setItem('username', data.content.username);
                $location.path('/home');

            }, function errorCallback(response) {
                console.log('失敗');
            });
        }