【问题标题】:Can Siblings Controllers communicate with each other without the help of the Parent - AngularJS兄弟姐妹控制器可以在没有父母帮助的情况下相互通信 - AngularJS
【发布时间】:2016-02-22 22:39:22
【问题描述】:

我正在使用 AngularJS 开发一个小应用程序。我的项目包含一个 Body.html 文件,其中包含 3 个视图:SideMenuHeaderContent,每个视图都有自己的 Controller 和 MainController parent - Body.html 的控制器。
标题的控制器可以更改侧面菜单中的属性 - 侧面菜单的打开/关闭状态。 并且侧面菜单控制器可以更改标题中的属性 - 标题的文本。
我可以使用主控制器,因为标题的控制器和侧面菜单控制器都可以引用主控制器。但数据不会是一致的。从第一个控制器更新数据不会影响第二个控制器中的数据(不使用 $watch)。

侧面菜单的控制器和标题的控制器(兄弟控制器)可以相互通信吗?没有父母的帮助?


正文.html

 <div>
     <!-- Header placeholder -->
     <div ui-view="header"></div>

     <!-- SideMenu placeholder -->
     <div ui-view="sideMenu"></div>

     <!-- Content placeholder -->
     <div ui-view></div>
 </div>

Header.html

 <div>
    {{ headerCtrl.text }}
 </div>
 <div ng-click="headerCtrl.openSideMenu()">
    --Open--
 </div>

HeaderController.js

 // sideMenuCtrl = ???
 headerCtrl.text = "Title";
 headerCtrl.openSideMenu = function()
 {
    sideMenuCtrl.isSideMenuOpen = true;
 };

SideMenu.html

 <div ng-class={ 'side-menu-open': sideMenuCtrl.isSideMenuOpen }>

     <div ng-repeat="menuItem in sideMenuCtrl.sideMenuItems"
          ng-click="sideMenuCtrl.selectMenuItem(menuItem)">
          {{ menuItem.text }}
     </div>
 </div>

SideMenuController.js

 // headerCtrl = ???
 sideMenuCtrl.selectMenuItem = function(menuItem)
 {
    headerCtrl.text = menuItem.text;
 }

【问题讨论】:

  • 您可能希望使用服务或工厂在控制器之间共享数据和逻辑。请参阅有关 servicefactory 的角度文档和指南
  • redux/flux 是一个很好的模式,可以让自上而下的数据流向所有兄弟姐妹和后代。或者,更一般地说,Eve​​ntEmitters,或现有父级上的 DOM 事件(事件冒泡)。全局变量(恐怖)可以在较小的应用程序中创造简单的奇迹。
  • A 可以使用服务/工厂在控制器之间共享数据。但是我会遇到与使用父范围相同的问题 - 数据不会组成。我需要使用 $watch 并监听每个控制器中的数据变化。我可以不使用 $watch 吗?
  • 查看我的答案,其中没有使用 $watch。

标签: javascript angularjs siblings


【解决方案1】:

正如我在评论中所说,您可以使用 AngularJS 服务在您的控制器之间共享一些数据。

app.service('AppContextService', function(){
    this.context = {
        isSideMenuOpen: false
    };
});

app.controller('SideMenuCtrl', ['$scope', 'AppContextService', function($scope, AppContextService) {
    // exposing the application context object to the controller.
    $scope.appContext = AppContextService.context;
}]);

app.controller('HeaderCtrl', ['$scope', 'AppContextService', function($scope, AppContextService) {
    $scope.appContext = AppContextService.context;
    $scope.openSideMenu = function()
    {
        $scope.appContext.isSideMenuOpen = true;
     };
}]);

然后调整 HTML 以使用您共享的 appContext 对象。

<div ng-class={ 'side-menu-open': appContext.isSideMenuOpen }>
   [...]
</div>

这是一个说明问题的工作小提琴:fiddle

这个答案涵盖了使用service 来满足您的需求,但我确信还有其他(也许更好)的方法来解决可能涉及其他Angular 功能甚至一些整体应用程序重构的问题.

为了深入挖掘,这个 SO 主题可能是一个好的开始:difference between service, factory and providers

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多