【问题标题】:Share data between controllers using Service AngularJs 1.6.1使用 Service AngularJs 1.6.1 在控制器之间共享数据
【发布时间】:2017-02-06 07:49:53
【问题描述】:

背景

我正在制作一个关于侏儒的人口普查应用程序。此应用程序显示所有 gnome 的列表并允许您对其进行过滤。

问题

问题是过滤器不起作用!我的gnome-filter 控制器无法与gnome-list 控制器通信。为了解决这个问题,我尝试通过在 StackOverlflow 中阅读此答案来创建服务:

但是,在创建了我认为是答案的精美复制品之后,它仍然无法正常工作。

代码

当应用程序首次加载时,gnome-list 向 gnome 人口普查服务器发出请求以获取所有 gnome 并显示它们。

但是,有很多侏儒,所以我为您提供了过滤它们的选项,并且只使用 gnome-filter 过滤掉那些有阅读​​头发的人。

不幸的是,即使我向服务器发出请求并得到答复,我的服务也无法正常工作...

/*global angular*/

(function() {
  var app = angular.module("census", []);

  app.controller("gnomeFilter", function(DataShareServ) {
    var self = this;
    self.listServ = DataShareServ;
    self.makeRequest = function() {
      self.listServ.request({
        hairColor: "red"
      });
    };
  });

  app.controller("gnomeList", function(DataShareServ) {
    var self = this;
    self.listServ = DataShareServ;
    self.listServ.request();
    self.list = self.listServ.data;
  });

  // Create the factory that share the Fact
  app.factory('DataShareServ', function($http) {
    var self = this;
    self.list = {};

    self.list.data = [];

    self.list.request = function(params) {
      var theUrl = 'https://gnome-shop-fl4m3ph03n1x.c9users.io/api/v1/gnomes';
      if (params.hairColor)
        theUrl = theUrl + "?hairColor=" + params.hairColor;

      $http({
        method: 'GET',
        url: theUrl,
        headers: {
          'Content-Type': 'application/json; charset=utf-8'
        }
      }).then(function successCallback(response) {
        self.list.data = response.data.entries;
        console.log("submitted");
      }, function errorCallback(response) {
        console.log('Error: ' + response);
      });
    };

    return self.list;
  });

})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>

<body>
  <!-- Search functionality -->
  <form ng-controller="gnomeFilter as filterCtrl" ng-submit="filterCtrl.makeRequest()">
    <button type="submit">Get Reddies !!</button>
  </form>

  <!-- Gnomes list -->
  <div ng-controller="gnomeList as listCtrl">
    <ul>
      <li ng-repeat="gnome in listCtrl.list">
        {{gnome.name}}
      </li>
    </ul>
  </div>
</body>

问题

  1. 我的代码有什么问题?我该如何解决?

【问题讨论】:

  • 我猜你可以通过使用 rootScope 在两个控制器之间轻松共享数据。
  • 我致力于服务,根据社区的说法,这似乎是更好的选择。
  • @Majid 这是一个糟糕的建议,不符合普遍接受的最佳做法

标签: javascript angularjs service controllers


【解决方案1】:

由于您将DataShareServ 分配给gnomeList 控制器的范围,因此您可以简单地遍历存储在您的服务中的数据,并在每次请求时更新和重新分配数据。这样您就不必处理在不同控制器上同步您的对象。

这样,html 看起来像这样:

<li ng-repeat="gnome in listCtrl.listServ.data">
   {{gnome.name}}
</li>

编辑

另请注意,您的代码中还有另一个问题。在gnomeList 控制器中,您正在调用服务的request 方法,该方法向某个端点发出异步请求并将其结果分配给本地变量,但您不必等待将控制器变量分配给服务变量。所以简单来说:

self.list = self.listServ.data;

这将始终为空,因为 http 请求是异步的。你需要处理 Promise(或类似的东西)。从角度看一下$q 服务:https://docs.angularjs.org/api/ng/service/$q

请注意,如果您采用我的解决方案,这并不重要,只是想指出这一点。

【讨论】:

    【解决方案2】:

    明显的问题是 self.list 正在被重新分配。

    self.list = response.data.entries 完成后,self.listDataShareServ.data 引用不同的对象。

    可以通过保持对同一对象的引用来解决

    self.list.length = 0;
    Object.assign(self.list, response.data.entries);
    

    另一个问题是控制器做了它不应该做的工作,这会导致设计问题。 $http 请求不应在控制器中执行。 DataShareServ 服务应该包含修改自己数据的方法。

    【讨论】:

    • 你好,你知道我能读到的关于角度架构的任何读物吗?你提出了一个很好的观点,我想了解一下。
    • 不是关于 Angular 的,不。这些是常见的 MVC(在 Angular 的上下文中它更像 MVVM)概念。我在这里的意思通常被称为“胖模型,瘦控制器”(“关注点分离”原则的一种特殊情况)。这是它可能看起来的示例,scotch.io/tutorials/making-skinny-angularjs-controllers,它与路由器有点过于复杂,但提供了一些视角。无论如何,如果你在控制器中有 $http,这意味着设计出了问题。
    • 顺便说一句,您在此处尝试实现的目标已经由 $resource 完成,它使用了与我在答案中描述的相同的自保湿对象技术。
    • 你能提供这个代码的最小工作示例吗?我会非常感激。
    • 您好,我已根据您的建议更新了我的问题。你介意再看一遍吗?
    猜你喜欢
    • 2015-12-15
    • 2014-03-22
    • 2013-05-28
    • 1970-01-01
    • 2014-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多