$scope 变量不在 $rootScope.$on 内更新
$scope variable not update within $rootScope.$on
这显示编号 1
和一个 更改 按钮。当我单击该按钮时,它应该触发 $state.go,并且在控制器内,它应该检测 $rootScope.$on
中的事件并将数字更新为 2
。但是,出于某种原因,即使使用 $digest 或 $apply,我也无法获取要更新的号码 (data.id
)。
http://plnkr.co/edit/3qHnIm?p=preview
HTML
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<script data-require="angular.js@*" data-semver="1.4.0-beta.5" src="https://code.angularjs.org/1.4.0-beta.5/angular.js"></script>
<script data-require="ui-router@*" data-semver="0.2.13" src="//rawgit.com/angular-ui/ui-router/0.2.13/release/angular-ui-router.js"></script>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title></title>
<meta name="description" content="" />
<meta name="viewport" content="width=device-width" />
</head>
<body class="container">
<div ui-view=""></div>
<div ng-controller="state2Ctrl">
<a href="#" ng-click="change()">Change</a>
</div>
<script src="app.js"></script>
<script src="controllers.js"></script>
</body>
</html>
state1.html
<p>{{ data.id }}</p>
JS
var app = angular.module('myapp', ['ui.router']);
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/state1/0');
$stateProvider
.state('state1', {
url: '/state1/:id',
controller: 'state1Ctrl',
templateUrl: 'state1.html'
});
});
app.controller('state2Ctrl', function ($scope, $rootScope, $state, $stateParams) {
$scope.i = 1;
$scope.change = function(){
console.log('change state1');
$state.go('state1', {id: $scope.i++});
};
});
app.controller('state1Ctrl', function ($scope, $rootScope, $state, $stateParams) {
$scope.data = {id: 1};
$rootScope.$on('$stateChangeSuccess', function(evt, toState, toParams, fromState, fromParams) {
console.log($scope.data);
$scope.$apply(function() {
$scope.data = {id: 2};
console.log($scope.data);
});
});
});
谁能找出我的错误,为什么 data.id
没有在视图中得到更新?
更新 1
根据下面的 Radim 回复,我稍微更改了代码以更好地反映我的真实代码:http://plnkr.co/edit/yyg0Hrl5IgzP4e44aRet?p=preview
基本我的情况没有父状态。我想要做的是从 SAME 状态,用新参数触发该状态并更改一些 $scope 变量对象。就这些了。
JS
var i = 1;
app.controller('state1Ctrl', function($scope, $rootScope, $state, $stateParams) {
$scope.change = function() {
console.log('change state1: ' + i);
$state.go('state1', {
id: i++
});
};
$scope.data = {
id: 1
};
$rootScope.$on('$stateChangeSuccess', function(evt, toState, toParams, fromState, fromParams) {
console.log('$stateChangeSuccess: ');
console.log($scope.data);
$scope.data = $scope.data || {};
$scope.data.id = toParams.id;
console.log('After assign:');
console.log($scope.data);
});
});
我点了4次Change后发现,$stateChangeSuccess
个事件堆积起来如下图。如果您能帮助解释并避免这种情况,我也不确定为什么。
原因是,你每次都在重新创建data
// this will create new reference to data
// in current scope, while not effecting any other (parent)
$scope.data = {id: 2};
如果您想更新现有参考,我们必须这样做
// here we work with existing reference
// if it was created, it will be used, the id property will be updated
$scope.data = $scope.data || {};
$scope.data.id = 2;
状态现在有了父级,我们将一直继承 $scope,所以我们可以将它用作 $scope.data
的共享持有者
$stateProvider
.state('state1Parent', {
template: '<div ui-view=""></div>',
controller: 'state1ParentCtrl',
});
$stateProvider
.state('state1', {
parent: 'state1Parent',
url: '/state1/:id',
controller: 'state1Ctrl',
templateUrl: 'state1.html'
});
控制器更新了 def:
app.controller('state1Ctrl', function ($scope, $rootScope, $state, $stateParams) {
// no $scope.data definition, used the inherited
//$scope.data = {id: 3};
$rootScope.$on('$stateChangeSuccess', function(evt, toState, toParams, fromState, fromParams) {
console.log($scope.data);
// because this state change listener still have access to $scope
// we can update the value of data.id
// because it is in fact parent reference
// se even next state will have access to it
//$scope.$apply(function() {
$scope.data = $scope.data || {};
$scope.data.id = toParams.id;
console.log($scope.data);
//});
});
});
还有一个父控制器,带有引用数据定义
app.controller('state1ParentCtrl', function ($scope, $rootScope, $state, $stateParams) {
$scope.data = { id : 1 };
})
检查一下here。
我并不是说我们应该走这条路。但试图说明问题是什么,以及如何解决
扩展:我们可以在没有父状态的情况下这样做吗?
来自扩展问题:
Basic I didn't have the situation with parent state in my case. What I want to do is from the SAME state, trigger that state with new params and change some $scope variable objects. That's all.
所以,这里有什么问题。
1) controller
生命周期最短,在angular世界。它只会在状态期间存在。一旦我们离开它,导航到其他 - 它会消失(如果没有内存泄漏挂钩)
2)controller的作用域会被销毁,一旦controller被销毁...
3) 我们必须将各州视为孤立的岛屿。如果我们确实可以访问状态 $scope
- 即使在内部声明 $rootScope.$on('$stateChangeSuccess'
- 我们确实可以访问当前控制器的当前状态...的 $scope 。事实上,我们为内存泄漏
创建了一个候选对象
app.controller('state1Ctrl', ...
...
$rootScope.$on('$stateChangeSuccess', ...
// HERE - $scope belongs to Controller, and its life cycle is very short
$scope.data =
4) 如果我们想改变一些值,在 "SAME state" 的中间 - 在转换之后我们必须将它移出。它不能处于当前状态,因为当前 state/view/controller(及其范围)将不相同。
5) 保存数据的方式是 - 服务(单例)或父类内部的模型(将通过 view/scope 继承继承)
6) $rootScope.$on
应该在某些 .运行() 方法中声明 - 在控制器之外。但在这种情况下,它似乎并没有增加任何价值。因为如果我们将共享数据放入某个服务中......我们可以在任何地方进行,例如在其他控制器中也是如此
这显示编号 1
和一个 更改 按钮。当我单击该按钮时,它应该触发 $state.go,并且在控制器内,它应该检测 $rootScope.$on
中的事件并将数字更新为 2
。但是,出于某种原因,即使使用 $digest 或 $apply,我也无法获取要更新的号码 (data.id
)。
http://plnkr.co/edit/3qHnIm?p=preview
HTML
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<script data-require="angular.js@*" data-semver="1.4.0-beta.5" src="https://code.angularjs.org/1.4.0-beta.5/angular.js"></script>
<script data-require="ui-router@*" data-semver="0.2.13" src="//rawgit.com/angular-ui/ui-router/0.2.13/release/angular-ui-router.js"></script>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title></title>
<meta name="description" content="" />
<meta name="viewport" content="width=device-width" />
</head>
<body class="container">
<div ui-view=""></div>
<div ng-controller="state2Ctrl">
<a href="#" ng-click="change()">Change</a>
</div>
<script src="app.js"></script>
<script src="controllers.js"></script>
</body>
</html>
state1.html
<p>{{ data.id }}</p>
JS
var app = angular.module('myapp', ['ui.router']);
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/state1/0');
$stateProvider
.state('state1', {
url: '/state1/:id',
controller: 'state1Ctrl',
templateUrl: 'state1.html'
});
});
app.controller('state2Ctrl', function ($scope, $rootScope, $state, $stateParams) {
$scope.i = 1;
$scope.change = function(){
console.log('change state1');
$state.go('state1', {id: $scope.i++});
};
});
app.controller('state1Ctrl', function ($scope, $rootScope, $state, $stateParams) {
$scope.data = {id: 1};
$rootScope.$on('$stateChangeSuccess', function(evt, toState, toParams, fromState, fromParams) {
console.log($scope.data);
$scope.$apply(function() {
$scope.data = {id: 2};
console.log($scope.data);
});
});
});
谁能找出我的错误,为什么 data.id
没有在视图中得到更新?
更新 1
根据下面的 Radim 回复,我稍微更改了代码以更好地反映我的真实代码:http://plnkr.co/edit/yyg0Hrl5IgzP4e44aRet?p=preview
基本我的情况没有父状态。我想要做的是从 SAME 状态,用新参数触发该状态并更改一些 $scope 变量对象。就这些了。
JS
var i = 1;
app.controller('state1Ctrl', function($scope, $rootScope, $state, $stateParams) {
$scope.change = function() {
console.log('change state1: ' + i);
$state.go('state1', {
id: i++
});
};
$scope.data = {
id: 1
};
$rootScope.$on('$stateChangeSuccess', function(evt, toState, toParams, fromState, fromParams) {
console.log('$stateChangeSuccess: ');
console.log($scope.data);
$scope.data = $scope.data || {};
$scope.data.id = toParams.id;
console.log('After assign:');
console.log($scope.data);
});
});
我点了4次Change后发现,$stateChangeSuccess
个事件堆积起来如下图。如果您能帮助解释并避免这种情况,我也不确定为什么。
原因是,你每次都在重新创建data
// this will create new reference to data
// in current scope, while not effecting any other (parent)
$scope.data = {id: 2};
如果您想更新现有参考,我们必须这样做
// here we work with existing reference
// if it was created, it will be used, the id property will be updated
$scope.data = $scope.data || {};
$scope.data.id = 2;
状态现在有了父级,我们将一直继承 $scope,所以我们可以将它用作 $scope.data
$stateProvider
.state('state1Parent', {
template: '<div ui-view=""></div>',
controller: 'state1ParentCtrl',
});
$stateProvider
.state('state1', {
parent: 'state1Parent',
url: '/state1/:id',
controller: 'state1Ctrl',
templateUrl: 'state1.html'
});
控制器更新了 def:
app.controller('state1Ctrl', function ($scope, $rootScope, $state, $stateParams) {
// no $scope.data definition, used the inherited
//$scope.data = {id: 3};
$rootScope.$on('$stateChangeSuccess', function(evt, toState, toParams, fromState, fromParams) {
console.log($scope.data);
// because this state change listener still have access to $scope
// we can update the value of data.id
// because it is in fact parent reference
// se even next state will have access to it
//$scope.$apply(function() {
$scope.data = $scope.data || {};
$scope.data.id = toParams.id;
console.log($scope.data);
//});
});
});
还有一个父控制器,带有引用数据定义
app.controller('state1ParentCtrl', function ($scope, $rootScope, $state, $stateParams) {
$scope.data = { id : 1 };
})
检查一下here。
我并不是说我们应该走这条路。但试图说明问题是什么,以及如何解决
扩展:我们可以在没有父状态的情况下这样做吗?
来自扩展问题:
Basic I didn't have the situation with parent state in my case. What I want to do is from the SAME state, trigger that state with new params and change some $scope variable objects. That's all.
所以,这里有什么问题。
1) controller
生命周期最短,在angular世界。它只会在状态期间存在。一旦我们离开它,导航到其他 - 它会消失(如果没有内存泄漏挂钩)
2)controller的作用域会被销毁,一旦controller被销毁...
3) 我们必须将各州视为孤立的岛屿。如果我们确实可以访问状态 $scope
- 即使在内部声明 $rootScope.$on('$stateChangeSuccess'
- 我们确实可以访问当前控制器的当前状态...的 $scope 。事实上,我们为内存泄漏
app.controller('state1Ctrl', ...
...
$rootScope.$on('$stateChangeSuccess', ...
// HERE - $scope belongs to Controller, and its life cycle is very short
$scope.data =
4) 如果我们想改变一些值,在 "SAME state" 的中间 - 在转换之后我们必须将它移出。它不能处于当前状态,因为当前 state/view/controller(及其范围)将不相同。
5) 保存数据的方式是 - 服务(单例)或父类内部的模型(将通过 view/scope 继承继承)
6) $rootScope.$on
应该在某些 .运行() 方法中声明 - 在控制器之外。但在这种情况下,它似乎并没有增加任何价值。因为如果我们将共享数据放入某个服务中......我们可以在任何地方进行,例如在其他控制器中也是如此