繁体   English   中英

Angular 1.6组件包含范围

[英]Angular 1.6 component transclusion scope

我试图弄清楚如何在Angular 1.6.4中将数据获取到组件包含中。 该场景具有一个组件,一个指令(尚未重写为组件)和一个用于组件间通信的服务。

angular.module('app')

  .service('svc', function() {
    this.connector = {};
  })

  .directive('first', ['svc', function($svc) { return {
    restrict: 'E',
    scope: { 'id': '@' },
    template: '<button ng-click="GetData()">get data</button>',
    controller: ['$scope', 'svc', function($scope, $svc) {
      $scope.connector = { data: [] };
      $svc.connector[$scope.id] = $scope.connector;
      $scope.GetData = function() {
        // This is a mock-up; I'm really doing a REST call.
        $scope.connector.data = [
          {id: 0, name: 'one'},
          {id: 1, name: 'two'}
        ];
      };
    }]    
  }; }])

  .component('second', {
    bindings: { parent: '@firstid' },
    transclude: true,
    template: '<ng-transclude></ng-transclude>',
    controller: ['svc', function($svc) {
      this.data = $svc.connector[this.parent];
      // Not sure what to do here
    }]
  })

;

我的HTML看起来像这样:

<first id="first-thing"></first>
<second firstid="first-thing">
  Where I expect my data to be: {{$ctrl | json}}<br/>
  ... but maybe here: {{$ctrl.$parent | json}}<br/>
  ... or even here: {{$parent | json}}<br/>
  <div ng-repeat="item in $ctrl.data">
    <p>Output: {{item.id}}/{{item.name}}</p>
  </div>
</second>

这些可能不会与require嵌套,这就是为什么我使用服务来存储数据的原因。 <first><second></second></first>不是一个选项。 在必要时,我可以使用一些$onInit解决方法来管理从组件控制器内部的服务获取数据。 我已经检查过,该服务在正确的时间包含正确的数据。 为了组件重用,我需要控制器包含内容。

巴塔朗列出了我所有的范围。 该指令具有预期的作用域$id 6(页面上还有其他内容)。 组件具有预期的作用域$id 7。 这些作用域根据我输入的内容和期望包含正确的数据。

我的问题是我还有一个附加作用域$id 。它似乎是已被超越的作用域,它是6和7的同级兄弟(这些是$id 5的同级项,我的页面控制器)。 正如我在HTML snark中所指出的那样,我希望组件包含在7中。如果8是7的子作用域,那会很好,但它是一个断开的兄弟。 我尝试了其他绑定,但是无法填充它们,因此它们只会抛出。 我显然做错了,因为我得到的是1.3版之前的用于包含范围继承的模型。

有人可以告诉我我误入歧途或至少将我引向正确的解决方案吗?

我知道了。 顺便说一句,我应该指出,根据互联网上的文献,我正在做一些我不应该做的事情。 我了解Angular的作者从试图将范围内的范围分离出来的来历,但我不同意该模型,至少在包含性方面不是如此。

angular.module('app')

  .service('svc', function() {
    this.connector = {};
  })

  .directive('first', ['svc', function($svc) { return {
    restrict: 'E',
    scope: { 'id': '@' },
    template: '<button ng-click="GetData()">get data</button>',
    controller: ['$scope', 'svc', function($scope, $svc) {
      $scope.connector = { data: [] };
      $svc.connector[$scope.id] = $scope.connector;
      $scope.GetData = function() {
        // This is a mock-up; I'm really doing a REST call.
        $scope.connector.data = [
          {id: 0, name: 'one'},
          {id: 1, name: 'two'}
        ];
        $scope.connector.data.Update($scope.connector.data);
      };
    }]    
  }; }])

  .component('second', {
    bindings: { parent: '@firstid' },
    transclude: true,
    template: '<ng-transclude></ng-transclude>',
    controller: ['$element', '$transclude', '$compile', 'svc', function($element, $transclude, $compile, $svc) {
      this.$onInit = () => { angular.extend(this, $svc.connector[this.parent]; };
      var parentid = $element.attr('firstid');
      $transclude((clone, scope) => {
        $svc.connector[parentid].Update = (data) => {
          angular.extend(scope, data);
          $element.append($compile(clone)(scope));
        };
      });
    }]
  })

;

这个怎么运作

这本质上是手动包含。 互联网上有太多关于手动包含的示例,人们可以手动修改DOM。 我不完全理解为什么有些人认为这是个好主意。 我们经历了太多的麻烦,将我们的标记(HTML)与格式(CSS)与代码(Angular指令/组件)与业务逻辑(Angular服务/工厂/提供者)分开,所以我不再回头将标记放入我的代码中

我找到了这篇文章,评论了Gustavo Henke的Angular问题,该问题使用$transclude的范围注册了回调。 有了这些关键信息,我认为我可以做更多的范围操作。

$transclude的代码似乎在摘要周期之外。 这意味着触摸其中的任何内容都不会收到自动更新。 幸运的是,我可以控制数据的更改事件,因此我完成了此回调。 在回调上,将更改数据并重新编译元素。 尚未在controller标记中绑定用于在服务中定位回调的键,因此必须从属性中手动检索它。

为什么这不好

组件不应在其自身范围之外修改数据。 我具体是这样做的。 Angular在执行此操作时似乎没有一个更合适的原始方法,而不会打破其他一些我认为对保持完整至关重要的担忧。

我认为其中存在“内存泄漏”,这就是说我的元素和作用域在每个更新周期中都没有得到正确处理。 我的数据库使用的数据很少,只有用户通过油门直接更新,并且在管理界面上。 我可以泄漏一些内存,而且我不希望用户在页面上停留足够长的时间以至于不会有所作为。

我的代码都希望事物在正确的位置,并在标记中命名正确的事物。 我实际的代码行数大约是此行的四倍,我正在检查是否有错误或遗漏。 这不是Angular方式,这意味着我可能做错了什么。

积分

如果没有Telerik文章 ,我现在应该坐在我墙上墙上甚至更血腥的标记旁边。

感谢本·莱什(Ben Lesh)撰写有关$compile 综合文章,其中有关于不应该使用它的适当免责声明。

托德莫托(Todd Motto) 在升级到1.6的帖子中帮助了很多人如何写一个不错的Angular 1.x组件。 正如人们可能期望的那样, 有关组件Angular文档提供的不仅仅是指向确切调用内容的特定指针。

AngularJS发行号7842的底部,有一些信息可以做类似的事情,甚至可能比我有更好的方法来更适当地管理作用域数据。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM