我正在使用AngularJS 1.5的新组件创建一组小部件。问题是,当多次使用相同的窗口小部件时,它们会以某种方式共享其控制器或范围。我认为有关组件的一个问题是它们的范围是完全孤立的吗?
我的主要html模板包含小部件:
<widget-list
title="Books"
class="col-xs-12 col-md-4">
</widget-list>
<widget-list
title="Movies"
class="col-xs-12 col-md-4">
</widget-list>
<widget-list
title="Albums"
class="col-xs-12 col-md-4">
</widget-list>
我的小部件模板:
<div class="widget widget-list">
<div class="panel b-a">
<div class="panel-heading b-b b-light">
<h5>{{$widget.title}}</h5>
<div class="pull-right">
<button type="button" class="btn btn-default btn-sm" ng-click="$widget.doSomething()">
Do something
</button>
</div>
</div>
<div class="panel-content">
{{$widget.content || 'No content'}}
</div>
</div>
</div>
我的小部件组件:
app.component('widgetList', {
templateUrl: 'template/widget/widget-list.html',
bindings: {
title : '@',
},
controllerAs: '$widget',
controller: function($timeout) {
$widget = this;
console.log('Title on init: ', $widget.title)
$timeout(function() {
console.log('Title after 3 seconds: ', $widget.title)
}, 3000)
$widget.doSomething = function() {
$widget.content = "Something";
}
}
});
运行我的代码时,这就是我的控制台的样子:
Title on init: Books
Title on init: Movies
Title on init: Albums
(3) Title after 3 seconds: Albums
渲染后,所有三个小部件都在其模板中显示No content
。但是,当点击三个小部件中的任何一个中的doSomething()
按钮时,只有最后一个小部件的内容更新为Something
。
这里发生了什么?为什么我的组件没有“隔离”?
答案 0 :(得分:3)
看起来你有一个名为$ widget的全局变量,试试这个:
var $widget = this;
而不是
$widget = this;
由于$ widget变量包含对最近初始化的控制器的引用(在本例中为第三个组件的控制器),因此它会造成混乱。
答案 1 :(得分:2)
您的代码的问题在于您在窗口范围内声明$widget
,这就是您的控制器打印最后一个值的原因,因为每次控制器实例化时它都会被覆盖。请改用var $widget
代码,您的代码就可以正常使用。
以下代码段解决了这个问题:
angular.module('app', [])
.component('widgetList', {
templateUrl: 'template/widget/widget-list.html',
bindings: {
title: '@',
},
controllerAs: '$widget',
controller: WidgetListController
});
function WidgetListController($timeout) {
var $widget = this;
console.log('Title on init: ', $widget.title)
$timeout(function() {
console.log('Title after 3 seconds: ', $widget.title)
}, 3000)
$widget.doSomething = function() {
$widget.content = "Something";
}
}
angular.element(document).ready(function() {
angular.bootstrap(document, ['app']);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.1/angular.min.js"></script>
<widget-list title="Books" class="col-xs-12 col-md-4">
</widget-list>
<widget-list title="Movies" class="col-xs-12 col-md-4">
</widget-list>
<widget-list title="Albums" class="col-xs-12 col-md-4">
</widget-list>
<script type="text/ng-template" id="template/widget/widget-list.html">
<div class="widget widget-list">
<div class="panel b-a">
<div class="panel-heading b-b b-light">
<h5>{{$widget.title}}</h5>
<div class="pull-right">
<button type="button" class="btn btn-default btn-sm" ng-click="$widget.doSomething()">
Do something
</button>
</div>
</div>
<div class="panel-content">
{{$widget.content || 'No content'}}
</div>
</div>
</div>
</script>