此展示号码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状态,用新的params触发该状态并更改一些$ 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次后,我发现了$stateChangeSuccess
事件的数量,如下面的屏幕截图所示。如果你能帮忙解释并避免这种情况,我不确定为什么。
答案 0 :(得分:1)
原因是,您每次都在重新创建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。
我不是说这是我们应该去的方式。但试图说明问题是什么,以及如何解决问题
EXTEND:如果没有父母州,我们可以这样做吗?
来自扩展问题:
基本我没有在我的情况下具有父状态的情况。我想要做的是从 SAME状态,触发状态与新参数并更改一些 $ scope 变量对象。就是这样。
那么,这里有什么问题。
1)controller
生命周期是角度世界中最短的。它只会在州内生活。一旦我们离开它,导航到其他 - 它将消失(如果没有内存泄漏挂钩)
2)一旦控制器被销毁,控制器的范围将被销毁......
3)我们必须将国家视为孤立的岛屿。如果我们确实可以访问状态$scope
- 即使在内部声明$rootScope.$on('$stateChangeSuccess'
中 - 我们也可以访问当前控制器的当前状态的$范围。事实上,我们为内存泄漏
app.controller('state1Ctrl', ...
...
$rootScope.$on('$stateChangeSuccess', ...
// HERE - $scope belongs to Controller, and its life cycle is very short
$scope.data =
4)如果我们想要改变某些值,那么“SAME state” - 转换后我们必须将其移出OUT。它不能处于当前状态,因为当前状态/视图/控制器(及其范围)将不相同。
5)如何保存数据的方式是 - 服务(单例)或父模型(将通过视图/范围继承继承)
6)$rootScope.$on
应该在某个.run()方法中声明 - 在控制器之外。但在这种情况下,它似乎没有增加任何价值。因为如果我们将共享数据放入某个服务......我们可以做任何事情,例如,在其他控制器中也是如此