AngularJS 模块/范围共享

Posted

技术标签:

【中文标题】AngularJS 模块/范围共享【英文标题】:AngularJS Modules/Scope Sharing 【发布时间】:2014-01-12 02:56:25 【问题描述】:

我最近开始使用 AngularJS,我现在构建应用程序的方式是这样的:

MainController.js

var app = angular.module('app', ['SomeController', 'MainController']);

app.controller('MainController', function ($scope) 
    // do some stuff

SomeController.js

var SomeController= angular.module('SomeController', []);

SomeController.controller('SomeController', function ($scope) 
    $scope.variable = "test";
    // do some otherstuff

我遇到的问题是范围没有在模块之间共享。例如,从 MainController 我无法获取变量“test”。

对此的最佳做法是什么?我是否将所有控制器存储在 1 个文件中的 1 个模块中? 我怎样才能拥有 2 个控制器的 1 页并在它们之间共享$scope,或者将所有内容都放在一个控制器中是否可以?

【问题讨论】:

这绝对是 X/Y 问题。如果你需要做这样的事情,那你就做错了。更新您的答案以解释您实际想要完成的工作。 基本上我在问我应该怎么做,我不一定需要这样做。 看我的回答,只要确保你将属于一起的东西打包在一起,而不是耦合不应该耦合的东西。 【参考方案1】:

您可以使用这样的服务:Live demo here (click).

JavaScript:

var otherApp = angular.module('otherApp', []);
otherApp.factory('myService', function() 
  var myService = 
    someData: ''
  ;
  return myService;
);
otherApp.controller('otherCtrl', function($scope, myService) 
  $scope.shared = myService;
);


var app = angular.module('myApp', ['otherApp']);

app.controller('myCtrl', function($scope, myService) 
  $scope.shared = myService; 
);

标记:

  <div ng-controller="otherCtrl">
    <input ng-model="shared.someData" placeholder="Type here..">
  </div>
  <div ng-controller="myCtrl">
  shared.someData
  </div>

Here's a nice article on sharing data with services.

您还可以嵌套控制器以使父控制器的范围属性由子范围继承: http://jsbin.com/AgAYIVE/3/edit

  <div ng-controller="ctrl1">
    <span>ctrl1:</span>
    <input ng-model="foo" placeholder="Type here..">
    <div ng-controller="ctrl2">
      <span>ctrl2:</span>
      foo
    </div>
  </div>

但是,子级不会更新父级 - 只有父级的属性会更新子级。

您将使用“点规则”让子级的更新影响父级。这意味着将您的属性嵌套在一个对象中。由于父母和孩子都有相同的对象,因此该对象的更改将反映在两个地方。这就是对象引用的工作方式。很多人认为最好的做法是不使用继承,而是将所有内容放在具有隔离范围的指令中。

【讨论】:

感谢您的解释,我应该说在一页/或部分页面上有多个模块是一种常见的做法吗?我知道我做错了。 @Chancho 您没有使用多个模块(也不应该使用)。您正在使用一个依赖于另一个模块的模块。这种耦合很好,但似乎你的想法不正确。假设Module A 是您创建的一种工具集。也许它有一个服务、目录和一个控制器,它们一起工作以提供一个很好的功能。现在,您正在创建一个应用程序,因此您创建了Module B。您决定 Module B 可以使用您在 Module A 中创建和打包的功能,因此 Module B 将依赖于 Module A 好吧,我想我现在明白了,但是驻留在模块中的控制器呢?基本上我现在正在做的是在里面创建一个带有控制器的模块。然后在另一个控制器中,我将该模块添加为该模块的依赖项。我认为这是我走错路的地方。 - 所以改写我的问题:我如何将多个控制器与其范围链接在一起? @Chancho 很可能,您确实需要服务解决方案,就像我说的那样。那是将这些范围链接在一起,因为它们都引用同一个对象。否则,他们的范围继承,但它是有限的。 jsbin.com/AgAYIVE/3/edit @Chancho 是的。请牢记大局——控制器并不意味着关心如何处理数据。控制器只是数据进出视图的枢纽。考虑到这一点 - 控制器在这里的工作只是将视图中的数据与服务中的数据相关联。然后依赖于该服务的其他东西可以用它做一些事情。如果您理解了这个概念,您应该会发现使用该数据的任何东西都存在问题,具体取决于控制器。【参考方案2】:

您可以使用$rootScope,每个 Angular 应用程序都只有一个根范围。

Reference

app.controller('MainController', function ($scope, $rootScope) 
    $rootScope.data = 'App scope data';

【讨论】:

每个模块都有自己的 $rootScope。 即使您可以访问这样的全局并共享状态——这被称为“公共耦合”,它是 5 分中的 4 级(内容耦合是最高的) )。 #badPractice、#tightCoupling、#theBadTypeOfComplexity 。 Mmmm...我正在运行 Angular 1.5.5,每个模块当然没有得到它自己的 $rootScope。 肯定有一个$rootScope,或者肯定应该存在,除非你做错了什么,比如在模块之间传递它或者将它分配给某个地方的另一个变量。我在 OP 的问题中没有看到任何表明该变量可能不是 static 变量的内容(这完全适用于 $rootScope,并避免了服务的复杂性)。跨度>

以上是关于AngularJS 模块/范围共享的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 angularJS 在多个项目之间共享代码

在angularjs中同步范围[重复]

如何在模块化的angularjs范围内测试指令?

AngularJS中模块之间的通信

Angularjs 范围之外的服务功能

AngularJS 模块中的run方法