我是AngularUI路由器的新手,并希望将它用于以下场景:
所有网页共有的 包括一个顶部导航栏,其中包含右侧带有按钮的菜单,以及填充下方空间的内容部分。该页面有几个页面,我映射到UI路由器状态(第1页,第2页,...)。每个页面都有自己的菜单项和自己的内容。 菜单需要与内容共享范围,因为它们相互作用(例如,保存按钮在内容中提交表单,只有在表单有效时才应启用它。)
HTML粗略如下:
<body>
<nav class="...">
<h1>my site</h1>
<div>MENU SHOULD GO HERE</div>
</nav>
<div class="row">
<div class="column ...">
CONTENT SHOULD GO HERE
</div>
</div>
</body>
现在,我正在为每个州使用两个并行视图和两个控制器。但这样,两个示波器/控制器无法互动。
那你怎么做到这一点?
答案 0 :(得分:22)
$ scope不是模型,它是对模型的引用,介于数据和介质之间。风景。如果两个或更多控制器中的$ scope需要共享一个模型/状态/数据,则通过注册角度服务来使用单个对象实例。可以将一个服务/工厂注入到任意数量的控制器中,然后一切都可以解决这个问题。
下面是一个工厂的演示,它连接了navbar&amp;中的$ scopes。使用ui-router http://plnkr.co/edit/P2UudS?p=preview的主体(仅限左侧标签)
ui-router(viewC是导航栏):
$stateProvider
.state('left', {
url: "/",
views: {
"viewA": {
controller: 'LeftTabACtrl',
template: 'Left Tab, index.viewA <br>' +
'<input type="checkbox" ng-model="selected2.data" />' +
'<pre>selected2.data: {{selected2.data}}</pre>'
},
{...},
"viewC": {
controller: 'NavbarCtrl',
template: '<span>Left Tab, index.viewC <div ui-view="viewC.list"></div>' +
'<input type="checkbox" ng-model="selected.data" />' +
'<pre>selected.data: {{selected.data}}</pre></span>'
}
}
})
工厂&amp;控制器:
app.factory('uiFieldState', function () {
return {uiObject: {data: null}}
});
app.controller('NavbarCtrl', ['$scope', 'uiFieldState', '$stateParams', '$state',
function($scope, uiFieldState, $stateParams, $state) {
$scope.selected = uiFieldState.uiObject;
}
]);
app.controller('LeftTabACtrl', ['$scope', 'uiFieldState', '$stateParams', '$state',
function($scope, uiFieldState, $stateParams, $state) {
$scope.selected2 = uiFieldState.uiObject;
}
]);
如您所见,工厂对象{uiObject: {data: null}}
通过uiFieldState
&amp;注入到控制器中。那么它只是$scope.selected = uiFieldState.uiObject;
用于将工厂连接到范围ng-model="selected.data"
.`
答案 1 :(得分:6)
您应该使用:
$on and $emit
发送控制器,用于发送数据。
angular.module('MyApp').controller('MyController', ['$scope', '$rootScope', function ($scope, $rootScope){
$rootScope.$emit('SomeEvent', data);
}]);
如何以一种安全的方式实现$ rootScope的示例,以便在使用后销毁和修复内容:
angular
.module('MyApp')
.config(['$provide', function($provide){
$provide.decorator('$rootScope', ['$delegate', function($delegate){
Object.defineProperty($delegate.constructor.prototype, '$onRootScope', {
value: function(name, listener){
var unsubscribe = $delegate.$on(name, listener);
this.$on('$destroy', unsubscribe);
},
enumerable: false
});
return $delegate;
}]);
}]);
控制器包含应该处理的数据。
angular.module('MyApp')
.controller('MySecondController', ['$scope', function MyController($scope) {
$scope.$onRootScope('SomeEvent', function(event, data){
console.log(data);
});
}
]);
您可以传入$ rootScope,而不是使用我们在配置中定义的$ scopes方法$ onRootScope。但是,这不是使用$ emit和$ onRootScope的推荐方法。
您可以使用$ broadcast,而不是使用$ emit。但是,随着应用程序的增长,这会给您带来非常大的性能问题。因为它通过所有控制器冒泡数据。
如果您的控制人是父母和孩子,他们不必使用$ rootScope。
以下是$ emit和$ broadcast:jsFiddle
之间差异的示例他们的确是性能差异: