正在删除 angular 个控制器实例
Deleting angular controller instance
为了快速阅读,问题在 "The problem" 下进行了简化,要了解更多信息,请在回答之前继续阅读背景和注释。谢谢!
问题
我想在刷新页面或移动到不同视图然后通过导航器返回同一视图时删除控制器实例 (nav.html
)。事实上,每次访问视图 X.html
时,我希望程序检查 X-controller.js
是否存在,如果确实存在,则在创建新实例之前将其删除。
我要走多远,这是我在网上找不到的 2 行解决方案,还是我正在寻找数小时的编码来完成这项工作?
背景
我的项目使用 $routeProvider
服务,而不是 ng-controller
指令。应用程序启动后,始终有两个视图,一个在顶部,您可以在其中通过控制器来回导航 "Home - Contact - Support"(逻辑上,nav.html
),另一个在底部,即 "Home" 或 "Contact" 等等。
在代码开始进行大量计算之前,我对这种安排没有任何问题。控制器的同一个实例更新了比它应该多的数据,计算了以前丢弃的数据,等等。我在网上阅读过有关删除控制器的信息,但据我所知,这并不容易。
答题前注意事项:
- 如果 'hours of coding' 的第二个选项是解决方案,我不希望任何人为我这样做,但是对文章或代码的引用将不胜感激,因为我没有发现任何有用的东西我自己的。
- 如果有更简单的解决方案仅在使用
ng-controller
而不是 $routeProvider
时适用,那么它不适合我。有超过 20 个视图和许多代码部分使用事件侦听器触发重定向到具有不同控制器的不同视图。我目前不打算将 $routeProvider
更改为 ng-controller
。
- 如果解决方案实际上并没有删除之前的实例,而是清除了 $scope 和 javascript 变量,那么这对我也适用。
- 我没有包含代码,因为这个问题与错误或错误无关,如果出于某种原因需要
$routeProvider
配置或一个视图和控制器的代码片段,请告诉我,我会包括用类似的虚拟代码替换分类部分的代码。
澄清编辑
我会举例说明。假设 X.html
是由 XCtrl.js
控制的视图。 $scope.test
在那个controller的开头$scope.test = 2
启动,点击视图中的按钮后$scope.test
变为3。另外,X视图一直显示$scope.test
.所以我移动到那个视图,点击按钮,然后看到屏幕上显示了 3。然后我通过导航器移动到"Home",然后回到"X",仍然显示3。但我想要显示的是 2 个,而不是 3 个。我希望在那个控制器中更新所有内容。
解决方案
最终我使用了不同的技术来解决这个问题。保存在本地存储中的所有数据都在影响 $scope 变量(变量太多无法跟踪,我没有注意到这一点)。为了解决这个问题,一旦访问了控制器 X 控制的视图,我就清除了本地存储键 localStorageService.set('keyUsed', []);
。假设一个 init 函数,那么清除本地存储的代码行放在该函数的顶部。
对于我最初认为遇到的问题,我仍在从下面的答案中标记出正确的解决方案。
Always have a '.' in your ng-models!
-- Miško Hevery (father of AngularJS)
很可能您遇到的问题是 $scope.test
而不是控制器本身。如果您的模板 x.html
将 test
的值引用为 {{test}}
(没有任何前缀),那么您很可能引用了错误范围的 test
。它通常是由于原型范围链相互扩展并回退到原型 属性 值而发生的。在这种情况下,为 XCtrl
控制器选择一些独特的东西,并将该控制器内的所有状态放入该命名空间。例如,使用 x
作为命名空间
$scope.x = {};
$scope.x.test = 2;
而不仅仅是
$scope.test = 2;
然后在 x.html
中将值引用为
{{x.test}}
这是 Angular 最佳实践之一。
另一个可以解决您的问题的最佳实践实际上根本不使用 $scope
,而是使用控制器实例本身来存储与 controllerAs
语法结合的状态:
index.html
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.min.js@1.5.8" data-semver="1.5.8" src="https://code.angularjs.org/1.5.8/angular.min.js"></script>
<script data-require="angular-route.min.js@1.5.8" data-semver="1.5.8" src="https://code.angularjs.org/1.5.8/angular-route.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-view>
</body>
</html>
script.js
angular.module('app', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/x', {
controller: 'xCtrl',
controllerAs: 'x',
templateUrl: 'x.html'
})
.when('/y', {
controller: 'yCtrl',
controllerAs: 'y',
templateUrl: 'y.html'
})
.otherwise({
redirectTo: '/x'
})
}])
.controller('xCtrl', [function() {
var x = this;
x.test = 2;
x.doSomething = function() {
x.test ++;
};
}])
.controller('yCtrl', [function() {
var y = this;
y.hello = 'Hello';
}])
x.html
<h1>X.html</h1>
<p>test = {{x.test}}</p>
<button ng-click="x.doSomething()">+1</button>
<a href="#/y">Link to Y</a>
y.html
<h1>Y.html</h1>
<p>{{y.hello}}</p>
<a href="#/x">Link to X</a>
现场演示:
https://plnkr.co/edit/EpUn94uWMliTaG5mvPxv?p=preview
链接:
为了快速阅读,问题在 "The problem" 下进行了简化,要了解更多信息,请在回答之前继续阅读背景和注释。谢谢!
问题
我想在刷新页面或移动到不同视图然后通过导航器返回同一视图时删除控制器实例 (nav.html
)。事实上,每次访问视图 X.html
时,我希望程序检查 X-controller.js
是否存在,如果确实存在,则在创建新实例之前将其删除。
我要走多远,这是我在网上找不到的 2 行解决方案,还是我正在寻找数小时的编码来完成这项工作?
背景
我的项目使用 $routeProvider
服务,而不是 ng-controller
指令。应用程序启动后,始终有两个视图,一个在顶部,您可以在其中通过控制器来回导航 "Home - Contact - Support"(逻辑上,nav.html
),另一个在底部,即 "Home" 或 "Contact" 等等。
在代码开始进行大量计算之前,我对这种安排没有任何问题。控制器的同一个实例更新了比它应该多的数据,计算了以前丢弃的数据,等等。我在网上阅读过有关删除控制器的信息,但据我所知,这并不容易。
答题前注意事项:
- 如果 'hours of coding' 的第二个选项是解决方案,我不希望任何人为我这样做,但是对文章或代码的引用将不胜感激,因为我没有发现任何有用的东西我自己的。
- 如果有更简单的解决方案仅在使用
ng-controller
而不是$routeProvider
时适用,那么它不适合我。有超过 20 个视图和许多代码部分使用事件侦听器触发重定向到具有不同控制器的不同视图。我目前不打算将$routeProvider
更改为ng-controller
。 - 如果解决方案实际上并没有删除之前的实例,而是清除了 $scope 和 javascript 变量,那么这对我也适用。
- 我没有包含代码,因为这个问题与错误或错误无关,如果出于某种原因需要
$routeProvider
配置或一个视图和控制器的代码片段,请告诉我,我会包括用类似的虚拟代码替换分类部分的代码。
澄清编辑
我会举例说明。假设 X.html
是由 XCtrl.js
控制的视图。 $scope.test
在那个controller的开头$scope.test = 2
启动,点击视图中的按钮后$scope.test
变为3。另外,X视图一直显示$scope.test
.所以我移动到那个视图,点击按钮,然后看到屏幕上显示了 3。然后我通过导航器移动到"Home",然后回到"X",仍然显示3。但我想要显示的是 2 个,而不是 3 个。我希望在那个控制器中更新所有内容。
解决方案
最终我使用了不同的技术来解决这个问题。保存在本地存储中的所有数据都在影响 $scope 变量(变量太多无法跟踪,我没有注意到这一点)。为了解决这个问题,一旦访问了控制器 X 控制的视图,我就清除了本地存储键 localStorageService.set('keyUsed', []);
。假设一个 init 函数,那么清除本地存储的代码行放在该函数的顶部。
对于我最初认为遇到的问题,我仍在从下面的答案中标记出正确的解决方案。
Always have a '.' in your ng-models!
-- Miško Hevery (father of AngularJS)
很可能您遇到的问题是 $scope.test
而不是控制器本身。如果您的模板 x.html
将 test
的值引用为 {{test}}
(没有任何前缀),那么您很可能引用了错误范围的 test
。它通常是由于原型范围链相互扩展并回退到原型 属性 值而发生的。在这种情况下,为 XCtrl
控制器选择一些独特的东西,并将该控制器内的所有状态放入该命名空间。例如,使用 x
作为命名空间
$scope.x = {};
$scope.x.test = 2;
而不仅仅是
$scope.test = 2;
然后在 x.html
中将值引用为
{{x.test}}
这是 Angular 最佳实践之一。
另一个可以解决您的问题的最佳实践实际上根本不使用 $scope
,而是使用控制器实例本身来存储与 controllerAs
语法结合的状态:
index.html
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.min.js@1.5.8" data-semver="1.5.8" src="https://code.angularjs.org/1.5.8/angular.min.js"></script>
<script data-require="angular-route.min.js@1.5.8" data-semver="1.5.8" src="https://code.angularjs.org/1.5.8/angular-route.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-view>
</body>
</html>
script.js
angular.module('app', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/x', {
controller: 'xCtrl',
controllerAs: 'x',
templateUrl: 'x.html'
})
.when('/y', {
controller: 'yCtrl',
controllerAs: 'y',
templateUrl: 'y.html'
})
.otherwise({
redirectTo: '/x'
})
}])
.controller('xCtrl', [function() {
var x = this;
x.test = 2;
x.doSomething = function() {
x.test ++;
};
}])
.controller('yCtrl', [function() {
var y = this;
y.hello = 'Hello';
}])
x.html
<h1>X.html</h1>
<p>test = {{x.test}}</p>
<button ng-click="x.doSomething()">+1</button>
<a href="#/y">Link to Y</a>
y.html
<h1>Y.html</h1>
<p>{{y.hello}}</p>
<a href="#/x">Link to X</a>
现场演示:
https://plnkr.co/edit/EpUn94uWMliTaG5mvPxv?p=preview
链接: