我有非常复杂的控制器(大约3K行代码)来演示仪表板。 Controller包含许多图表,网格表等。
例如,我将网格表逻辑移动到下面提到的名为wmGridActionItems
的指令中。请注意,它使用父范围:
app.directive('wmGridActionItems', ['$rootScope', '$timeout', function ($rootScope, $timeout) {
return {
restrict: 'E',
templateUrl: 'views/grid-action-items.html',
link: function (scope, elem, attrs) {
// logic goes here
}
};
}]);
和HTML:
<div ui-grid="gridActionItemsOptions"
ui-grid-auto-resize
ui-grid-pagination
ui-grid-selection
ui-grid-auto-resize
ui-grid-resize-columns>
</div>
所以在主控制器HTML中,我只写:<wm-grid-action-items></wm-grid-action-items>
我无法在其他地方使用此指令,但至少我将我的BIG控制器划分为几个小指令,这些指令可以帮助我处理仪表板。
我做错了什么?这是好习惯吗? Angular有其他方法可以解决这个问题吗?
修改的
这是我的$StateProvider
信息中心视图:
$stateProvider
.state('sidemenu.dash', {
url: '/dshmngr',
abstract: true,
views: {
'content': {
templateUrl: 'views/dashboard/dashboard_manager.html',
controller: 'DashboardMngrCtrl'
}
}
})
.state('sidemenu.dash.main', {
url: '/main',
views: {
'content': {
templateUrl: 'views/dashboard/dashboard-main.html',
controller: 'DashboardNewCtrl'
}
}
})
.state('sidemenu.dash.drill', {
url: '/drill/:type',
views: {
'content': {
templateUrl: 'views/dashboard/dashboard-tag-details.html',
controller: 'DashboardDetailedCtrl'
}
}
})
谢谢,
答案 0 :(得分:3)
你的目标是正确的方向。以指令的形式将大型控制器分解为更小的组件是可行的方法,但我建议您进行一些更改。
隔离指令的范围并定义指令明确期望的数据。这样就可以立即看到数据指令接受的内容。
为便于测试,请将指令与Controller
配对。
根据以上两条建议,您的指令应如下所示:
app.directive('wmGridActionItems', [function () {
return {
controller: 'WmGridActionItemsController'
restrict: 'E',
templateUrl: 'views/grid-action-items.html',
scope: {
gridActionItemsOptions: '=gridActionItemsOptions'
}
link: function (scope, elem, attrs) {
// DOM manpulation (if needed) goes here
}
};
}]);
app.controller('WmGridActionItemsController', ['$cope', '$timeout', function ($cope, $timeout) {
// logic goes here
}]);
然后您将调用上述指令,如:
<wm-grid-action-items grid-action-item-options="gridActionItemsOptions">
</wm-grid-action-items>
我建议你也阅读这篇很棒的blog post,详细解释“组件模式”。
另请注意,在定义隔离范围时通过显式指定共享模型不是唯一的方法。另一种共享数据的方法是将模型作为服务(请参阅related reading)。
答案 1 :(得分:1)
我向你推荐的“良好做法”是single responsibility principle。
您构建的每个组件(指令/控制器/服务)绝不能做多件事。如果您避免此错误,您的组件将更具可重用性,可读性和可维护性。
当然,这种做法不仅仅是角度。
你尊重的,我建议你:
避免将所有业务代码放在控制器中,而是使用服务(或提供程序)。服务更加强大,因为它们允许使用角度依赖注入系统。
指令应仅包含DOM操作。
角度指令/控制器/服务是一种View/ViewModel/Model模式。尽量记住这一点。
编辑:您的每个指令都可以拥有一个控制器。您可以将指令放在另一个指令模板中,然后使用链接函数的最后一个参数(controllers
)和指令require
参数进行指令之间的通信。
示例:(coffeescript)假设我有一个可以在其他容器内部的容器,并且可能还包含一个小部件:
angular.module('dashboard')
.directive('dashboardWidget', [() ->
restrict: 'E'
templateUrl : '/views/dashboard/widget.html'
require: ['^^dashboardContainer']
scope:
'model': '='
controller: 'DashboardWidgetController'
controllerAs: 'DashboardWidget'
# default => post link (children already instanciated)
link: ($scope, element, attrs, ctrls) ->
[parentDashboardContainerController] = ctrls
# some very small code (mainly events), the real code is in the controller
return
])
angular.module('dashboard')
.directive('dashboardContainer', [() ->
restrict: 'E'
templateUrl : '/views/dashboard/container.html'
require: ['?^^dashboardContainer', '?^ngController']
scope:
'model': '='
controller: 'DashboardContainerController'
controllerAs: 'DashboardContainer'
# default => post link (children already instanciated)
link: ($scope, element, attrs, ctrls) ->
[parentDashboardContainerController, ngController] = ctrls
# some very small code (mainly events), the real code is in the controller
return
])