【问题标题】:Share large object between controllers in angular以角度在控制器之间共享大对象
【发布时间】:2017-12-10 16:10:38
【问题描述】:

我正在尝试使用服务在两个控制器之间共享数据。但是用 XHR 更改数据后,我没有看到数据更新。

angular    
  .module('appy', [])
  .service('MyService', function($http){
    return {
       dataToChange: {
       },
       ajaxy: function(url){
         var self = this;
         setTimeout(function(){
           console.log('now we are in the service!');
           self.dataToChange = 'something new';
           console.log(this.dataToChange);
         }, 1000);
       }
    };
  })
  .controller('c1', ['$scope', 'MyService', function($scope, MyService){
    $scope.myService = MyService;
    $scope.ajaxy = function(){
      $scope.myService.ajaxy();
    };
  }])
  .directive('dirOne', function(){
    return {
      restrict: 'E',
      templateUrl: 'dirone-temp.html'
    };
  })
  .controller('c2', ['$scope', 'MyService', function($scope, MyService){

      $scope.myData = MyService.dataToChange;  

  }])
  .directive('dirTwo', function(){
    return {
      restrict: 'E',
      templateUrl: 'dirtwo-temp.html'
    };
  });

但是当ajaxy 进行更新时,什么都没有发生。我尝试按照this question 的建议进行设置。没有喜悦。我还尝试添加手表。

$scope.$watch(function(){
  return MyService.ajaxy();
}, function(oldVal, newVal){
  $scope.somethingToChange = newVal;
  console.log($scope.somethingToChange);
});

但仍然没有任何反应。这个物体也很大。我不想$watch它。

JSBIN

【问题讨论】:

  • 首先仅供参考,在setTimeout 中,您的this 指的是window。您需要将 setTimeout 回调绑定到您的对象(但是,这不会解决您的主要问题)。
  • 好点。当我嘲笑这个时,我什至没有想到这一点。谢谢!
  • 我建议使用根控制器,以便您可以获取该控制器中的数据并在 c1 和 c2 之间共享。
  • @sniels 为什么你认为这是最好的选择?您将如何设置“根控制器”?谢谢。
  • 我并不是说这是最好的建议,但它在过去对我有用。我会试着举一个例子。

标签: javascript angularjs angularjs-directive xmlhttprequest


【解决方案1】:

当您想要共享您的数据时,您必须共享一个对象(就像您给出的示例一样)并且永远不要替换该对象。如果您确实替换了服务中的对象,则 $scope 仍将引用旧对象,这就是您的问题。

  1. 您将 MyService.dataChange 设置为一个空对象。
  2. 您将该对象注入到您的控制器范围内
  3. 当您调用 ajaxy() 时,您将 MyService.dataChange 更改为字符串 'something new'。此时,作用域仍然持有对旧对象的引用,而不是对字符串的引用。

要解决这个问题,您需要向该对象添加一个属性,而不是替换 MyService.dataChange。当您绑定到共享对象的该属性时,您会注意到您必须运行 ajaxy() 两次。要解决这个问题,您需要使用角度 $timeout 而不是使用超时。

angular    
  .module('appy', [])
  .service('MyService', function($http, $timeout){
    return {
       // never replace this object, put the values you want to share as a property inside.
       sharedObject: {
         name: 'old value'
       },
       ajaxy: function(url){
         var self = this;
         // use the angular version of $timeout to make sure your scope is in sync
         $timeout(function(){
           console.log('now we are in the service!');
           self.sharedObject.name = 'new value';
           console.log(self.sharedObject);
         }, 1000);
       }
    };
  })
  .controller('c1', ['$scope', 'MyService', function($scope, MyService){
    $scope.myData = MyService.sharedObject;
    $scope.ajaxy = function(){
      MyService.ajaxy();
    };
  }])
  .directive('dirOne', function(){
    return {
      restrict: 'E',
      templateUrl: 'dirone-temp.html'
    };
  })
  .controller('c2', ['$scope', 'MyService', function($scope, MyService){ 
    $scope.myData = MyService.sharedObject;
  }])
  .directive('dirTwo', function(){
    return {
      restrict: 'E',
      templateUrl: 'dirtwo-temp.html'
    };
  });
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body ng-app="appy">
  
  <dir-one ng-controller="c1"></dir-one>
  <hr>
  <dir-two ng-controller="c2"></dir-two>  
  
  <script id="dirone-temp.html" type="text/ng-template">
    template one
    <button ng-click="ajaxy()">something time consuming</button>
    <div>{{myData.name}}</div>
  </script>
  
  <script id="dirtwo-temp.html" type="text/ng-template">
    template two
    <div>{{myData.name}}</div>
  </script>
</body>
</html>

【讨论】:

  • @thomas,我没有使用 rootcontroller 和共享范围,因为这种策略看起来确实更简洁。
  • 谢谢!可悲的是,我现在已经很晚了,我必须在早上检查一下。如果ajaxy 是实际的$http() get,这将如何改变?
  • 只需将 $timeout 替换为 $http.get(url).then( function success(response) { self.sharedObject.data=response.data;}, function error(response){ ...} );
  • @thomas 不要忘记在早上接受答案,如果它对你有用。
  • 嗯。我将不得不考虑将$timeout 替换为$http。我想这正是我最初开始的地方!谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多