AngularJS与ui.router $状态在异步时不起作用

时间:2014-06-28 20:52:10

标签: javascript angularjs angular-ui-router

我在使用AngularJSui.router方面遇到了问题。

我有一个应用程序,基本上是用户写信息,发送到服务器,当服务器回答时,我将当前状态更改为通道列表。

我的问题是,通过使用asynchroneus系统,我失去了更改当前状态的能力,没有任何错误,演示:

以下演示是可以的,因为它不使用asynchroneus系统(参见控制台):

代码: http://jsfiddle.net/dievardump/x2tMT/

演示已满: http://jsfiddle.net/dievardump/x2tMT/embedded/result/

这是一个不好的(见控制台)。

代码: http://jsfiddle.net/dievardump/f9rSQ/

演示已满: http://jsfiddle.net/dievardump/f9rSQ/embedded/result/

这两个样本之间的唯一区别在于“platform.channels”状态的声明:

console.log('goes to platform.game');
$state.go('platform.game', {
    type: 'gameType',
    id: 1
});

VS

setTimeout(function () {
    console.log('should go to platform.game');
    $state.go('platform.game', {
        type: 'gameType',
        id: 1
    });
}, 1000);

可在本地轻松导入完整演示:

工作:

                  

<div ui-view></div>
<script>


var myApp = angular.module('myApp', ['ui.router']);
myApp.config(function($stateProvider, $urlRouterProvider) {
        $urlRouterProvider.otherwise("/signin");

        $stateProvider
            .state('platform', {
                url: '/platform',
                data: {
                    permissions: ['auth']
                },
                template: "<section class='platform'>platform<div ui-view></div></section>",
                controller: function($state) {
                    console.log('platformController');
                }
            });
});

myApp.config(function($stateProvider, $urlRouterProvider) {
    $stateProvider
        .state('signin', {
            url: "/signin",
            template: "<section id='connect' class='connect'><form name='connection' action='' ng-submit='login(connection)'><input placeholder='Choose a nickname' ng-model='nickname' autocomplete='off' /><button><span>Send</span></button></form><p class='error' ng-show='error != null'>{{error}}</p></section>",
            controller: function($scope, $state) {
                $scope.error = null;
                $scope.nickname = null;

                $scope.login = function(form) {
                    var value = $scope.nickname.replace(/[^a-zA-Z0-9]/g, '');
                    if (value.length >= 3) {
                        $state.go('platform.channels');
                    } else {
                        $scope.error = 'only characters and numbers. length must be >= 3';
                    }
                }
            }
        });
});

myApp.config(function($stateProvider, $urlRouterProvider) {

    $stateProvider.state('platform.channels', {
        url: "/channels",
        template: "<section id='channels' class='channels'>channels</section>",
        controller: function($state) {
            console.log('channelController');
            console.log('goes to platform.game');
            $state.go('platform.game', {
                type: 'gameType',
                id: 1
            });
        }
    })
});

myApp.config(function($stateProvider, $urlRouterProvider) {
    $stateProvider.state('platform.game', {
            url: "/game/:type/:id",
            template: "<section id='game' class='game'>game</section>",
            controller: function() {
                console.log('gameController');
            }
        });
});


angular.bootstrap(document, ['myApp']);
</script>

不工作:                   

<div ui-view></div>
<script>


var myApp = angular.module('myApp', ['ui.router']);
myApp.config(function($stateProvider, $urlRouterProvider) {
        $urlRouterProvider.otherwise("/signin");

        $stateProvider
            .state('platform', {
                url: '/platform',
                data: {
                    permissions: ['auth']
                },
                template: "<section class='platform'>platform<div ui-view></div></section>",
                controller: function($state) {
                    console.log('platformController');
                }
            });
});

myApp.config(function($stateProvider, $urlRouterProvider) {
    $stateProvider
        .state('signin', {
            url: "/signin",
            template: "<section id='connect' class='connect'><form name='connection' action='' ng-submit='login(connection)'><input placeholder='Choose a nickname' ng-model='nickname' autocomplete='off' /><button><span>Send</span></button></form><p class='error' ng-show='error != null'>{{error}}</p></section>",
            controller: function($scope, $state) {
                $scope.error = null;
                $scope.nickname = null;

                $scope.login = function(form) {
                    var value = $scope.nickname.replace(/[^a-zA-Z0-9]/g, '');
                    if (value.length >= 3) {
                        $state.go('platform.channels');
                    } else {
                        $scope.error = 'only characters and numbers. length must be >= 3';
                    }
                }
            }
        });
});

myApp.config(function($stateProvider, $urlRouterProvider) {

    $stateProvider.state('platform.channels', {
        url: "/channels",
        template: "<section id='channels' class='channels'>channels</section>",
        controller: function($state) {
            console.log('channelController');
            setTimeout(function () {
                console.log('should go to platform.game');
                $state.go('platform.game', {
                    type: 'gameType',
                    id: 1
                });
            }, 1000);
        }
    })
});

myApp.config(function($stateProvider, $urlRouterProvider) {
    $stateProvider.state('platform.game', {
            url: "/game/:type/:id",
            template: "<section id='game' class='game'>game</section>",
            controller: function() {
                console.log('gameController');
            }
        });
});


angular.bootstrap(document, ['myApp']);
</script>

$ state.go在setTimeout中不起作用的原因是什么?

1 个答案:

答案 0 :(得分:2)

你的演示不起作用的原因是超时,当你导致角度知识发生变化时它很简单,角度保持不知道发生的变化因此它不会更新。

解决方案是使用角度方式来做到这一点。 angular提供$timeout服务。

在此处详细了解:https://docs.angularjs.org/api/ng/service/ $ timeout

工作(此处修复了异步演示):http://jsfiddle.net/f9rSQ/2/

PS你应该总是使用angular的方式或ng- *指令来处理异步更改,如果你通过纯javascript执行它们就不会触发按钮点击事件监听器。为了使它们发射,您可以强制角度运行$digest周期,这是使用ng-click$http等时以更干净的方式实际发生的事情。