javascript 当控制器 $scope 变量更改时,AngularJS 视图不更新?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32431623/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 15:16:04  来源:igfitidea点击:

AngularJS View not updating when Controllers $scope variables changed?

javascriptangularjs

提问by JohnWick

basically my issue is that I have a AngularJS view (home.html) which contains a variable in double brackets like so: {{message}}

基本上我的问题是我有一个 AngularJS 视图 (home.html),其中包含一个双括号中的变量,如下所示:{{message}}

When the $scope.message variable is modified, the view with does not update, although it should? I have tried adding $scope.$apply() which results in an exception along the lines of 'Action in Progress'

当 $scope.message 变量被修改时,视图不会更新,尽管它应该更新?我曾尝试添加 $scope.$apply() 这会导致“正在进行的操作”中的异常

Check my code below. The {{message}} part in home.html is not being updated when $scope.doLogin is called in MainCtrl, even though I have set $scope.message to a new value in that function.

在下面检查我的代码。在 MainCtrl 中调用 $scope.doLogin 时,home.html 中的 {{message}} 部分并未更新,即使我已将 $scope.message 设置为该函数中的新值。

Any help is greatly appreciated and if any further info is needed, please ask.

非常感谢任何帮助,如果需要任何进一步的信息,请询问。

index.html

索引.html

<!DOCTYPE html>

<html ng-app="myApp">
<head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
    <link href="stylesheet.css" rel="stylesheet">

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.4/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.4/angular-route.min.js"></script>
    <base href="/">

    <script src="https://cdnjs.cloudflare.com/ajax/libs/ngStorage/0.3.9/ngStorage.js"></script>
    <script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>

</head>
<body>

    <div ng-controller="MainCtrl">
        <nav class="navbar navbar-default">
            <div class="container">
                <div class="navbar-header">
                    <a class="navbar-brand" href="#">TriviaAttack</a>
                </div>
                <div id="navbar" class="navbar-collapse collapse">
                    <form id="loginForm" class="navbar-form navbar-right">
                        <div class="form-group">
                            <input type="text" placeholder="Email" class="form-control" ng-model="loginData.username">
                        </div>
                        <div class="form-group">
                            <input type="text" placeholder="Password" class="form-control" ng-model="loginData.password">
                        </div>
                        <div class="form-group">
                            <button type="submit" class="btn btn-success" ng-click="doLogin()">Sign In</button>
                        </div>                  
                    </form>
                </div>
            </div>
        </nav>
    </div>

    <div ng-view>

    </div>
    </div>

    <script src="./app/app.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js">

</body>
</html>

home.html

主页.html

<div>
    <h1>Welcome to the Home Page</h1>
    <p>{{message}}</p>
</div>

app.js

应用程序.js

var myApp = angular.module('myApp',['ngRoute', 'ngStorage']);

myApp.controller('MainCtrl', ['$rootScope', '$scope', '$location', 
    function($rootScope, $scope, $location) {

    $scope.message = 'testing message';

    $scope.loginData = {
        username: '',
        password: '',
        loggedIn: false
    }

    $scope.doLogin = function() {

        $scope.message = 'message changed!';
        $scope.$apply();

        Auth.doLogin($scope.loginData.username, $scope.loginData.password)
        .success(function(data) {
            if (data.success) {
                AuthToken.setToken(data.token);
                $location.path('/home');
                console.log($scope.loginData.loggedIn);
            }
        });

        $scope.loginData = {};
    }

}]);

//Middleware for all requests which adds the users token to the HTTP header.
myApp.factory('TokenInterceptor', ['$q', '$location', '$localStorage',
    function($q, $location, $localStorage) {

    //On each request, check if the user is logged in with a valid token.
    var interceptor = {
        request: function(config) {

            config.headers['X-Authorization-Token'] = $localStorage.token;
            return config;

        },
        responseError: function(response) {
            if(response.status === 401 || response.status === 403) {
                $location.path('/login');
            }
            return $q.reject(response);
        }
    };
    return interceptor;
}]);

myApp.config(['$routeProvider','$locationProvider','$httpProvider',
    function($routeProvider, $locationProvider, $httpProvider) {

        $routeProvider.
            when('/', {
                templateUrl: './app/views/landingpage.html',
                controller: 'MainCtrl'
            }).
            when('/home', {
                templateUrl: './app/views/home.html',
                controller: 'MainCtrl'
            }).
            otherwise({
                redirectTo: '/'
            });


        $locationProvider.html5Mode(true);

        $httpProvider.interceptors.push('TokenInterceptor');

    }

]);

console.log('app.js loaded!');

回答by NavyCody

Each time a view is loaded ,the controller code with new scope executes so the new message is not reflected. So the flow be like landingPage's controller which is MainCtrl with its scope when $scope.doLogin is executed will change the $scope.message variable to "Message Changed" and upon changing location to home , the MainCtrl is assigned to home page with new scope which would continue executing the very first line of MainCtrl i.e.

每次加载视图时,都会执行具有新作用域的控制器代码,因此不会反映新消息。所以流程就像landingPage的控制器,当 $scope.doLogin 执行时,它的作用域是 MainCtrl 会将 $scope.message 变量更改为“Message Changed”,并且在将 location 更改为 home 时,MainCtrl 被分配给具有新作用域的主页这将继续执行 MainCtrl 的第一行,即

  $scope.message = 'testing message';

As you have decided to use common controller for login and home pages

由于您已决定使用通用控制器进行登录和主页

Try removing controller option in

尝试删除控制器选项

when('/', {
  templateUrl: './app/views/landingpage.html',
  controller: 'MainCtrl'
}).
when('/home', {
  templateUrl: './app/views/home.html',
  controller: 'MainCtrl'
}) 

And assign controller in

并分配控制器

<div ng-controller="MainCtrl">
    <!--omitted-->
    <div ng-view></div>
</div>

Or else other options would be to pass parameters or use ui-router wherein nested views would automatically inherit from parent controllers without rerunning the controller logic.

或者其他选项是传递参数或使用 ui-router,其中嵌套视图将自动从父控制器继承,而无需重新运行控制器逻辑。

回答by Medet Tleukabiluly

Problem is in controller coverage

问题在于控制器覆盖范围

<div ng-controller="MainCtrl">
    <!--omitted-->
</div>
<div ng-view></div>

Your $scope.messageis tight to your MainCtrl, so when ng-viewis populated, you except that it has MainCtrl, but indeed it's outside of that div, so just doesn't see that variable, to make it work, insert ng-viewto MainCtrldiv like shown below

你的$scope.message对你的MainCtrl很紧,所以当ng-view被填充时,你除了它有MainCtrl,但实际上它在那个 div 之外,所以只是没有看到那个变量,为了使它工作,插入ng-viewMainCtrldiv如下图所示

<div ng-controller="MainCtrl">
    <!--omitted-->
    <div ng-view></div>
</div>

But here's the actual problem

但这里是实际问题

You tend to use ng-route but you don't have any route configurations, ng-viewwill never be populated with home.htmlunless you configure you routeProvider, first of all, make some routes like described here, perform your form action, redirect to page and populate views accordingly, it should work.

您倾向于使用 ng-route 但您没有任何路由配置,除非您配置 routeProvider,否则ng-view永远不会被填充home.html,首先,创建一些像这里描述的路由,执行您的表单操作,重定向到页面并填充视图因此,它应该起作用。