[英]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.