UI-Router - 状态变化时范围没有被破坏?

时间:2021-12-02 13:14:56

I'm a new user to AngularJS and ui-router, and I'm trying to turn my head around on how the scope is managed. I was expecting the scope of an active controller would be destroyed when it becomes inactive on state change, however, it doesn't appear to be the case.

我是AngularJS和ui-router的新用户,我正试图改变管理范围的方式。我期望当状态改变变为非活动状态时,活动控制器的范围将被销毁,但是,似乎并非如此。

I've modified the example from UI-Router's website to illustrate the situation (see plunker below). Every time when the state route1.list/route2.list is triggered, they will emit an event on $rootScope. On receiving the event, a debug statement will be printed to console.

我已经从UI-Router的网站修改了这个例子来说明情况(参见下面的plunker)。每次触发state route1.list / route2.list时,它们都会在$ rootScope上发出一个事件。收到事件后,将在控制台上打印调试语句。

By toggling between the two states a few times, it is observed that all the controllers initialized previously responded the the event. So it appears that the scopes created by them have never been destroyed. Is this behavior expected? If so, what should I do such that only active controllers will respond to an event?

通过在两个状态之间切换几次,观察到先前初始化的所有控制器都响应该事件。所以看来它们创建的范围从未被破坏过。这种行为有望吗?如果是这样,我该怎么办才能让只有主动控制器响应一个事件呢?

Plunker

Plunker

Debug message printed on Console: UI-Router  - 状态变化时范围没有被破坏?

在控制台上打印调试消息:

Code:

码:

var myapp = angular.module('myapp', ["ui.router"])
myapp.config(function($stateProvider, $urlRouterProvider){

// For any unmatched url, send to /route1
$urlRouterProvider.otherwise("/route1")

here is the route1

这是route1

$stateProvider
  .state('route1', {
      url: "/route1",
      templateUrl: "route1.html"
  })
    .state('route1.list', {
        url: "/list",
        templateUrl: "route1.list.html",
        controller: function($rootScope, $scope){
          $rootScope.$emit("eventCT1");
          $rootScope.$on("eventCT2", fn);
          function fn () {
            console.log("Controller 1 receives an event emitted by Controller 2");
          }
          $scope.items = ["A", "List", "Of", "Items"];
        }
    })

and here is route 2

这是路线2

  .state('route2', {
      url: "/route2",
      templateUrl: "route2.html"
  })
    .state('route2.list', {
        url: "/list",
        templateUrl: "route2.list.html",
        controller: function($rootScope, $scope){
          $rootScope.$emit("eventCT2");
          $rootScope.$on("eventCT1", fn);
          function fn () {
            console.log("Controller 2 receives an event emitted by Controller 1");
          }
          $scope.things = ["A", "Set", "Of", "Things"];
        }
    })
 ...

2 个解决方案

#1


5  

If we want to do something with

如果我们想做点什么

1) $rootScope inside of the controller (which has very limited lifetime),

1)控制器内部的$ rootScope(寿命非常有限),

2) we must destroy that, when controller (its $scope in fact) is being destroyed

2)当控制器(实际上是其范围)被销毁时,我们必须销毁它

So, this is the way how to hook and unhook

所以,这是如何挂钩和解钩的方式

// get remove function
var removeMe = $rootScope.$on("eventCT2", ...);

// call that function
$scope.$on("$destroy", removeMe)

But, in the case above, we should not even try to

但是,在上面的情况下,我们甚至不应该尝试

1) create some controller action for one state...

1)为一个州创建一些控制器动作......

2) and expect it will be called in another controller from different state

2)并期望它将在不同状态的另一个控制器中调用

These will never live together

这些永远不会生活在一起

#2


-1  

If you are using Ionic with Angular, you could use the life cycle events like so:

如果您使用Ionic与Angular,您可以使用生命周期事件,如下所示:

$scope.$on("$ionicView.beforeEnter", function(){
   //Do something every time this controller is the active scope.
})

You could play around with the other events provided in the above link as well. And it's probably best practise to minimize the use of $emit, which will lead to more predictable code and fewer state mutations.

您也可以使用上述链接中提供的其他活动。最小化$ emit的使用可能是最好的做法,这将导致更可预测的代码和更少的状态突变。

#1


5  

If we want to do something with

如果我们想做点什么

1) $rootScope inside of the controller (which has very limited lifetime),

1)控制器内部的$ rootScope(寿命非常有限),

2) we must destroy that, when controller (its $scope in fact) is being destroyed

2)当控制器(实际上是其范围)被销毁时,我们必须销毁它

So, this is the way how to hook and unhook

所以,这是如何挂钩和解钩的方式

// get remove function
var removeMe = $rootScope.$on("eventCT2", ...);

// call that function
$scope.$on("$destroy", removeMe)

But, in the case above, we should not even try to

但是,在上面的情况下,我们甚至不应该尝试

1) create some controller action for one state...

1)为一个州创建一些控制器动作......

2) and expect it will be called in another controller from different state

2)并期望它将在不同状态的另一个控制器中调用

These will never live together

这些永远不会生活在一起

#2


-1  

If you are using Ionic with Angular, you could use the life cycle events like so:

如果您使用Ionic与Angular,您可以使用生命周期事件,如下所示:

$scope.$on("$ionicView.beforeEnter", function(){
   //Do something every time this controller is the active scope.
})

You could play around with the other events provided in the above link as well. And it's probably best practise to minimize the use of $emit, which will lead to more predictable code and fewer state mutations.

您也可以使用上述链接中提供的其他活动。最小化$ emit的使用可能是最好的做法,这将导致更可预测的代码和更少的状态突变。