【问题标题】:Sharing Data between Child Directives在子指令之间共享数据
【发布时间】:2017-03-08 16:28:25
【问题描述】:

我定义了三个指令:

  • 家长

    这应该在其他两个指令之间共享变量 - 孩子一和孩子二。

  • 儿童一号

    这包含一个代表搜索词的输入字段。每当这种情况发生变化时,我都会使用链接函数来更新存储在父控制器中的变量。

    在实际使用中,我将根据该术语进行搜索并更新数组。但是为了简单起见,我只想创建一个长度为 1 的新数组,我想用搜索词作为它的值来填充它。

  • 孩子二

    这应该会显示结果数组。

由于某种原因,这不起作用,如果我将数组的长度设置为 0 并推送该值,我将在 Child Two 中看到视图更新(我已经注释掉了实现这一点的代码),但我想了解为什么设置数组值不起作用。

我知道一个服务在这里很合适,但是这个指令可能会在同一个页面上重复使用多次,所以我不希望页面上每个项目之间的范围发生冲突。

为什么视图没有用我当前使用的代码更新?

var app = angular
  .module('SampleApplication', [])
  .directive('parent', function() {
    return {
      restrict: 'E',
      transclude: true,
      template: "<div ng-transclude></div>",
      controller: function($scope) {
        this.searchTerm = "";
        this.arrayContainingSearchTerm = [{value: ''}];
      
        this.updateSearchTerm = function(searchTerm) {
          this.searchTerm = searchTerm;
          
          //When this array is assigned - it doesn't get updated in the view
          this.arrayContainingSearchTerm = [{value: searchTerm}];
          
          //This will update the view.
          //this.arrayContainingSearchTerm.length = 0;
          //this.arrayContainingSearchTerm.push([{value: searchTerm}]);
        };
        
      }
    }
  })
  .directive('childOne', function() {
    return {
      restrict: 'E',
      require: '^^parent',
      template: "<div><h1>Child One</h1><input ng-model='searchTerm'></input></div>",
      link: function(scope, element, attrs, parentController) {
        scope.$watch('searchTerm', function(newValue, oldValue) {
          parentController.updateSearchTerm(newValue);
        });
      }
    }
  })
  .directive('childTwo', function() {
    return {
      restrict: 'E',
      require: '^^parent',
      template: "<div><h1>Child Two</h1><h2>Value below should be: {{searchTerm}}</h2><h2>{{arrayContainingSearchTerm}}</h2></div>",
      link: function(scope, element, attrs, parentController) {
        scope.searchTerm = parentController.searchTerm;
        scope.arrayContainingSearchTerm = parentController.arrayContainingSearchTerm;
      }
    }
  })
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>


<div ng-app="SampleApplication">
  <parent>
    <child-one></child-one>
    <child-two></child-two>
  </parent>
</div>

【问题讨论】:

    标签: javascript angularjs angularjs-directive angularjs-scope


    【解决方案1】:

    子作用域自动继承父作用域,并且可以使用 $parent / 需要父控制器专门访问父作用域,但请注意兄弟姐妹不能[轻松]访问彼此的作用域。因此,解决方案是更新父范围并将父范围更改反映回目标子范围。

    您不需要更新子作用域,因为子作用域会自动从父作用域继承。另外,不要观看 searchTerm ngModel,只需在 childOne 指令中使用 attrs.ngModel。

    var app = angular
    .module('SampleApplication', [])
    .directive('parent', function() {
      return {
        restrict: 'E',
        transclude: true,
        template: "<div ng-transclude></div>",
        controller: function($scope) {
          this.searchTerm = "";
          this.arrayContainingSearchTerm = [{value: ''}];
    
          this.updateSearchTerm = function(searchTerm) {
            this.searchTerm = searchTerm;
    
            //When this array is assigned - it doesn't get updated in the view
            this.arrayContainingSearchTerm = [{value: searchTerm}];
    
            //This will update the view.
            //this.arrayContainingSearchTerm.length = 0;
            //this.arrayContainingSearchTerm.push([{value: searchTerm}]);
          };
    
        }
      }
    })
    .directive('childOne', function() {
      return {
        restrict: 'E',
        require: '^^parent',
        template: "<div><h1>Child One</h1><input ng-model='searchTerm'></input></div>",
        link: function(scope, element, attrs, parentController) {
            // Just use attrs.ngModel
            parentController.updateSearchTerm(attrs.ngModel);
        }
      }
    })
    .directive('childTwo', function() {
      return {
        restrict: 'E',
        require: '^^parent',
        template: "<div><h1>Child Two</h1><h2>Value below should be: {{searchTerm}}</h2><h2>{{arrayContainingSearchTerm}}</h2></div>",
        link: function(scope, element, attrs, parentController) {
           // Comment/remove this since the scope is automatically inherit from parent scope
          //scope.arrayContainingSearchTerm = parentController.arrayContainingSearchTerm;
          //scope.searchTerm = parentController.searchTerm;
           // scope.arrayContainingSearchTerm = parentController.arrayContainingSearchTerm;
    
        }
      }
    })
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
    
    
    <div ng-app="SampleApplication">
      <parent>
        <child-one></child-one>
        <child-two></child-two>
      </parent>
    </div>

    【讨论】:

    • 感谢您的回答。我无法使用 parentController.$scope 语法访问父控制器的范围。另外,您的意思是在链接函数中为自己分配变量吗?请问sn-p可以给个答案吗?
    • 感谢您的回答。我不能将此答案与 Transclusion 一起使用,因为父范围会丢失,但在我的情况下,transclusion 并不重要。我重写了我的指令以硬编码 child-one 和 child-two 并且指令相互通信没有任何问题。
    【解决方案2】:

    您的第二条指令不知道您之后所做的更改 - 您需要 $watch 他们:

    var app = angular
    .module('SampleApplication', [])
    .directive('parent', function() {
      return {
        restrict: 'E',
        transclude: true,
        template: "<div ng-transclude></div>",
        controller: function($scope) {
          this.searchTerm = "";
          this.arrayContainingSearchTerm = [{value: ''}];
    
          this.updateSearchTerm = function(searchTerm) {
            this.searchTerm = searchTerm;
    
            //When this array is assigned - it doesn't get updated in the view
            this.arrayContainingSearchTerm = [{value: searchTerm}];
    
            //This will update the view.
            //this.arrayContainingSearchTerm.length = 0;
            //this.arrayContainingSearchTerm.push([{value: searchTerm}]);
          };
    
        }
      }
    })
    .directive('childOne', function() {
      return {
        restrict: 'E',
        require: '^^parent',
        template: "<div><h1>Child One</h1><input ng-model='searchTerm'></input></div>",
        link: function(scope, element, attrs, parentController) {
          scope.$watch('searchTerm', function(newValue, oldValue) {
            parentController.updateSearchTerm(newValue);
          });
        }
      }
    })
    .directive('childTwo', function() {
      return {
        restrict: 'E',
        require: '^^parent',
        template: "<div><h1>Child Two</h1><h2>Value below should be: {{searchTerm}}</h2><h2>{{arrayContainingSearchTerm}}</h2></div>",
        link: function(scope, element, attrs, parentController) {
          scope.arrayContainingSearchTerm = parentController.arrayContainingSearchTerm;
          scope.searchTerm = parentController.searchTerm;
          scope.$watch(function() {
            scope.arrayContainingSearchTerm = parentController.arrayContainingSearchTerm;
          });
    
        }
      }
    })
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
    
    
    <div ng-app="SampleApplication">
      <parent>
        <child-one></child-one>
        <child-two></child-two>
      </parent>
    </div>

    【讨论】:

    • 感谢您的回答,这行得通,但我想知道是否有一种方法可以在没有手表的情况下实现这一目标?如果我必须查看大量变量,我可以看到我的代码变得非常冗长。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-12
    相关资源
    最近更新 更多