在阅读一些关于它的文章后,我打算将我的代码转换为使用controller as
语法。但是,我很惊讶使用controller as
语法,不能再直接使用父控制器的变量,我的意思是,用旧方式(使用$ scope),我可以这样做:
// <div ng-controller="ParentCtrl">
// <div ng-controller="ChildCtrl"></div>
// </div>
//
app.controller('ParentCtrl', function ($scope) {
$scope.x.title = 'Some title';
});
app.controller('ChildCtrl', function ($scope) {
console.log($scope.x.title);
});
但是controller as
,我必须这样做(感谢question}):
// <div ng-controller="ParentCtrl as pc">
// <div ng-controller="ChildCtrl as cc"></div>
// </div>
//
app.controller('ParentCtrl', function () {
this.x.title = 'Some title';
});
app.controller('ChildCtrl', function ($scope) {
console.log($scope.pc.x.title);
});
这很烦人,因为1)。我必须知道在html页面中我的父控制器被命名为pc。 2)。我无法进行批量搜索并替换$scope => vm (or this)
,因为如果继承该属性,它将无效。
有人可以告诉我controller as
引入时的理由是什么?
如果我使用大量的范围继承,我是否正确,那么我应该避免使用controller as
?或者范围继承被认为是有害的,应该不鼓励吗?
答案 0 :(得分:3)
不,您不能进行机械搜索和替换,因为您当前将所有不同范围的值混合在一起并且控制器 - 因为语法旨在将它们分开。特别是为了避免某些父作用域使用title
然后你已经离开并在子作用域中再次使用title
并隐藏父作用域的情况。或者更糟糕的是,当你所做的只是在一个子范围内掩盖它时,你认为你正在更新父title
。
因此,您必须确定哪个父作用域包含您要访问的每个值。这意味着如果要将其从范围继承树中拉出来,您确实必须知道用于引用该范围模型的名称。
更好的解决方案是使用指令,或从1.5角向前的组件。代替子控制器爬行范围以获取父值,而不是将所需的值作为参数传递给指令/组件。然后父母负责公开他希望孩子访问的值。或者,您可以使用指令或控制器的require
属性来创建仅在嵌入特定父级时工作的子级,并且父级控制器将直接绑定到子级控制器中。
以下是angular documentation的示例。请注意,在myPane控制器内部,您可以以this.tabsCtrl
的形式访问父控制器,重要的是,孩子决定使用父控制器的名称,而不是父控制器:
angular.module('docsTabsExample', [])
.component('myTabs', {
transclude: true,
controller: function MyTabsController() {
var panes = this.panes = [];
this.select = function(pane) {
angular.forEach(panes, function(pane) {
pane.selected = false;
});
pane.selected = true;
};
this.addPane = function(pane) {
if (panes.length === 0) {
this.select(pane);
}
panes.push(pane);
};
},
templateUrl: 'my-tabs.html'
})
.component('myPane', {
transclude: true,
require: {
tabsCtrl: '^myTabs'
},
bindings: {
title: '@'
},
controller: function() {
this.$onInit = function() {
this.tabsCtrl.addPane(this);
console.log(this);
};
},
templateUrl: 'my-pane.html'
});