【问题标题】:How to use angular 1.x services to update one component from another?如何使用 Angular 1.x 服务从另一个组件更新一个组件?
【发布时间】:2018-03-23 04:47:30
【问题描述】:

所以我有一个父组件,其中包含大量较小的组件。一般的想法是我需要一个组件来接收输入中的数据并将其显示在另一个组件上。这就是我所拥有的,它不太管用,之后有更多关于问题的详细信息:

const app = angular.module('app', []);

app.service('dataService', function() {
  let data = {
    key1: "",
    key2: "",
    key3: {
      key4: 0,
      key5: 0
    }
  }

  this.getKey1 = function() {
    return data.key1;
  }

  this.updateKey1 = function(str) {
     data.key1 = str;
  }
}

app.component('display', {
  controller: displayController,
  template: '<p>{{ keyOne }}</p>'
});

app.component('input', {
  controller: inputController,
  template: '<input ng-model="$ctrl.key1" ng-change="sendKey1()">'
}

function displayController($scope, dataService) {
  const vm = this;
  const self = $scope;
  vm.$onInit = onInit;
  function onInit() {
    self.keyOne = dataService.getKey1();
  }
}

function inputController($scope, dataService) {
  const vm = this;
  const self = $scope;
  vm.$onInit = onInit;
  function onInit() {
    self.sendKey1 = function() {
      dataService.updateKey1(vm.key1)
  }
}

所以更新有效,但它没有将它传递给显示组件。如果我在更新数据对象后记录它是正确的,但它不会显示在视图中。

【问题讨论】:

    标签: javascript angularjs data-binding service components


    【解决方案1】:

    看看A Tale of Frankenstein and Binding to Service Values in Angular.js

    以下是正在发生的事情的简要总结:

    1. displayController 执行 self.keyOne = dataService.getKey1()。这会将一个空字符串分配给$scope.keyOne
    2. 在视图中,表达式{{ keyOne }} 监视$scope.keyOne 的变化。它最初的计算结果为 "",因此视图中存在一个空字符串。
    3. inputControllerdataService.data.keyOne 更改为某个值,例如 hello world
    4. 在视图中,表达式{{ keyOne }} 再次评估$scope.keyOne 作为摘要循环的一部分进行更改。 问题: $scope.keyOne 仍然是一个空字符串! displayController 不知道从 dataService.data.keyOne 获取最新值。

    幸运的是,修复很简单。您只需要获取对 data 对象的引用,以便在观察更改时正确评估 data.keyOne

    app.service('dataService', function() {
      let data = {
        key1: ""
      }
    
      //Expose the data object
      this.getData = function() {
        return data;
      }
    }
    
    app.component('display', {
      controller: displayController,
      //Evaluate the current value of keyOne in the data object
      template: '<p>{{ data.keyOne }}</p>'
    });
    
    function displayController($scope, dataService) {
      const vm = this;
      const self = $scope;
      vm.$onInit = onInit;
      function onInit() {
        //Get a static reference to the data object.
        //The data object itself shouldn't change, but its properties will.
        self.data = dataService.getData();
      }
    }
    

    【讨论】:

      【解决方案2】:

      你正在更新一个字符串 data.key1 = str;

      let data = { key1: "", key2: "", key3: { key4: 0, key5: 0 } }

      Angular 不绑定组件之间的字符串,只绑定对象。

      看这里https://plnkr.co/edit/wfwyyGpcMKOSHGFdg2DS?p=preview

      var app = angular.module('plunker', ['ngRoute', 'ngAnimate', 'ngSanitize']);
      
      app.service('dataService', function() {
        let data = {
          key1: "",
          key2: "",
          key3: {
            key4: 0,
            key5: 0
          }
        }
      
        this.getData = function() {
          return data;
        }
      
        this.updateKey1 = function(str) {
          data.key1 = str;
        }
      });
      
      
      
      app.component('inputc', {
        controller: inputController,
        template: '<input ng-model="$ctrl.key1" ng-change="sendKey1()">'
      });
      
      app.component('display', {
        controller: displayController,
        template: '<p>{{ data.key1 }}</p>'
      });
      
      function displayController($scope, dataService) {
        const vm = this;
        const self = $scope;
        vm.$onInit = onInit;
      
        function onInit() {
          self.data = dataService.getData();
        }
      }
      
      function inputController($scope, dataService) {
        const vm = this;
        const self = $scope;
        vm.$onInit = onInit;
      
        function onInit() {
          self.sendKey1 = function() {
            dataService.updateKey1(vm.key1)
          }
        }
      }
      <!DOCTYPE html>
      <html ng-app="plunker">
      
        <head>
          <meta charset="utf-8" />
          <title>AngularJS Plunker</title>
          <script>document.write('<base href="' + document.location + '" />');</script>
          <link href="style.css" rel="stylesheet" />
          <script src="https://code.angularjs.org/1.6.2/angular.js"></script>
          <!-- By setting the version to snapshot (available for all modules), you can test with the latest master version -->
          <!--<script src="https://code.angularjs.org/snapshot/angular.js"></script>-->
          <script src="https://code.angularjs.org/1.6.2/angular-route.js"></script>
          <script src="https://code.angularjs.org/1.6.2/angular-animate.js"></script>
          <script src="https://code.angularjs.org/1.6.2/angular-sanitize.js"></script>    
          <script src="app.js"></script>
        </head>
      
        <body>
          <inputc></inputc>
          <display></display>
        </body>
        
        
      
      </html>

      【讨论】:

        【解决方案3】:

        看看这篇文章:https://www.aurorasolutions.io/blog/angularjs-cross-component-communication/

        很好地解释了你的问题。

        希望对你有帮助!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-06-12
          • 2017-09-07
          • 2019-06-15
          • 2019-04-04
          • 1970-01-01
          • 2021-07-23
          • 2020-07-01
          • 2019-03-08
          相关资源
          最近更新 更多