如何惯用地手动销毁作用域并在 AngularJS 中重新创建它?
How to idiomatically, manually destroy scope & re-create it in AngularJS?
我正在尝试使用 UI-router 来管理我的应用程序中的状态更改。我认为在动态路由上更改状态会导致当前范围被破坏,并为模板创建新范围并重新插入新内容,例如:
$stateProvider
.state('foo', {
url: '/:id'
views: {
'foo@': {
templateUrl: 'partials/foo.html',
controller: 'Foo',
controllerAs: 'FooCtrl as foo'
}
}
});
我认为每次用户导航到具有不同 ID 的路由时,上面的状态都会破坏并创建 FooCtrl。因此,运行在每个路由更改中使用位于 FooCtrl 中的初始化函数,以使用来自被注入控制器的服务的正确数据来初始化当前视图。我一直在我的控制器中监听 $scope.$destroy
函数在这些状态变化时变为 运行,但它们没有被调用。
我很好奇的是,创建和销毁控制器以获得我上面描述的功能的惯用方法是什么?另外,在 AngularJS 中是否有更惯用的方法来实现同样的事情?
谢谢!
更新:
为了在使用 $state.go()
时销毁并重新创建控制器,您必须将 {reload: true}
选项作为第三个参数传递,如下所示。
$state.go('foo', {id: '1'}, {reload: true})
如 Radim 所述,无需调用 {reload: true}
即可重新实例化控制器。目前,我正在监听 $stateChangeStart
以确保状态确实正在更新。在看到它是之后,我正在监听 $scope.$on('$destroy')
并且它没有触发。所以出于某种原因,状态正在改变,而控制器没有被销毁和重新实例化。
更新工作
我犯的错误是在我最深的嵌套视图中我使用了绝对路径。这似乎使控制器从一个状态持续到另一个状态。当我使嵌套视图相对时,它们将被破坏并在状态变化时重新创建,如 Radim 所述。
有a working plunker。 UI-Router 默认执行您期望的操作。它在每次更改状态时重新实例化控制器,即即使仅更改了一个参数 (id)
我稍微调整了上面的状态定义:
// instead of this
.state('/:id', {
views: {
'foo@': {
templateUrl: 'partials/foo.html',
controller: 'Foo',
controllerAs: 'FooCtrl as foo'
}
}
})
// wee need this
.state('myState', {
url: '/:id',
views: {
'foo@': {
templateUrl: 'partials/foo.html',
controller: 'FooCtrl',
controllerAs: 'foo'
}
}
})
并且这个 FooCtrl
会在我们导航到具有不同 id
的状态 'MyState'
时登录控制台
// register controller
.controller('FooCtrl', FooCtrl)
// this function will be our controller, called any time new id is passed
function FooCtrl($scope, $stateParams) {
console.log('init with id: ' + $stateParams.Id + ', state params:')
console.log($stateParams)
var foo = {};
foo.$stateParams = $stateParams
return foo;
};
FooCtrl.$inject = ['$scope', '$stateParams'];
中查看
我正在尝试使用 UI-router 来管理我的应用程序中的状态更改。我认为在动态路由上更改状态会导致当前范围被破坏,并为模板创建新范围并重新插入新内容,例如:
$stateProvider
.state('foo', {
url: '/:id'
views: {
'foo@': {
templateUrl: 'partials/foo.html',
controller: 'Foo',
controllerAs: 'FooCtrl as foo'
}
}
});
我认为每次用户导航到具有不同 ID 的路由时,上面的状态都会破坏并创建 FooCtrl。因此,运行在每个路由更改中使用位于 FooCtrl 中的初始化函数,以使用来自被注入控制器的服务的正确数据来初始化当前视图。我一直在我的控制器中监听 $scope.$destroy
函数在这些状态变化时变为 运行,但它们没有被调用。
我很好奇的是,创建和销毁控制器以获得我上面描述的功能的惯用方法是什么?另外,在 AngularJS 中是否有更惯用的方法来实现同样的事情?
谢谢!
更新:
为了在使用 $state.go()
时销毁并重新创建控制器,您必须将 {reload: true}
选项作为第三个参数传递,如下所示。
$state.go('foo', {id: '1'}, {reload: true})
如 Radim 所述,无需调用 {reload: true}
即可重新实例化控制器。目前,我正在监听 $stateChangeStart
以确保状态确实正在更新。在看到它是之后,我正在监听 $scope.$on('$destroy')
并且它没有触发。所以出于某种原因,状态正在改变,而控制器没有被销毁和重新实例化。
更新工作 我犯的错误是在我最深的嵌套视图中我使用了绝对路径。这似乎使控制器从一个状态持续到另一个状态。当我使嵌套视图相对时,它们将被破坏并在状态变化时重新创建,如 Radim 所述。
有a working plunker。 UI-Router 默认执行您期望的操作。它在每次更改状态时重新实例化控制器,即即使仅更改了一个参数 (id)
我稍微调整了上面的状态定义:
// instead of this
.state('/:id', {
views: {
'foo@': {
templateUrl: 'partials/foo.html',
controller: 'Foo',
controllerAs: 'FooCtrl as foo'
}
}
})
// wee need this
.state('myState', {
url: '/:id',
views: {
'foo@': {
templateUrl: 'partials/foo.html',
controller: 'FooCtrl',
controllerAs: 'foo'
}
}
})
并且这个 FooCtrl
会在我们导航到具有不同 id
'MyState'
时登录控制台
// register controller
.controller('FooCtrl', FooCtrl)
// this function will be our controller, called any time new id is passed
function FooCtrl($scope, $stateParams) {
console.log('init with id: ' + $stateParams.Id + ', state params:')
console.log($stateParams)
var foo = {};
foo.$stateParams = $stateParams
return foo;
};
FooCtrl.$inject = ['$scope', '$stateParams'];
中查看