在指令link函数的transclude函数中,"futureParentElement"是如何使用的?
In the transclude function of a directive link function, how is "futureParentElement" used?
在 angular documentation for the compile service (starting at line 412) 中有对传递到指令的链接函数的 transclude 函数的描述。
相关部分为:
function([scope], cloneLinkingFn, futureParentElement)
其中(第 212 行):
futureParentElement
: defines the parent to which the cloneLinkingFn
will add the cloned elements.
default: $element.parent()
resp. $element
for transclude:'element'
resp. transclude:true
.
only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)
and when the cloneLinkinFn
is passed,
as those elements need to created and cloned in a special way when they are defined outside their usual containers (e.g. like <svg>
).
See also the directive.templateNamespace
property.
然而,我没有看到 futureParentElement
的意义。它说
defines the parent to which the cloneLinkingFn will add the cloned elements.
但是你在 cloneLinkingFn
中这样做:
transclude(scope, function (clone) {
some_element.append(clone);
});
而且如果不首先定义克隆函数,就不能使用 transclude 函数。
usage/a futureParentElement
的正确用法是什么?
可以通过查看 git blame of compile.js
: the commit that added futureParentElement
is https://github.com/angular/angular.js/commit/ffbd276d6def6ff35bfdb30553346e985f4a0de6
找到答案
在提交中有一个测试指令的测试svgCustomTranscludeContainer
directive('svgCustomTranscludeContainer', function() {
return {
template: '<svg width="400" height="400"></svg>',
transclude: true,
link: function(scope, element, attr, ctrls, $transclude) {
var futureParent = element.children().eq(0);
$transclude(function(clone) {
futureParent.append(clone);
}, futureParent);
}
};
});
通过测试 html <svg-custom-transclude-container><circle cx="2" cy="2" r="1"></circle>
的编译行为:
it('should handle directives with templates that manually add the transclude further down', inject(function() {
element = jqLite('<div><svg-custom-transclude-container>' +
'<circle cx="2" cy="2" r="1"></circle></svg-custom-transclude-container>' +
'</div>');
$compile(element.contents())($rootScope);
document.body.appendChild(element[0]);
var circle = element.find('circle');
assertIsValidSvgCircle(circle[0]);
}));
因此,如果您使用指令创建 SVG 图像,其模板将嵌入的 SVG 内容包装在 <svg> ... </svg>
标记中,那么该 SVG 图像将无效(根据某种定义),如果您不要将正确的 futureParentElement
传递给 $transclude
.
为了了解无效的实际含义,除了源代码中的测试之外,我基于单元测试中的指令创建了 2 个指令,并使用它们尝试创建具有部分内容的 SVG 图像圆圈。一个使用 futureParentElement
:
<div><svg-custom-transclude-container-with-future><circle cx="1" cy="2" r="20"></circle></svg-custom-transclude-container></div>
还有一个相同但不同的:
<div><svg-custom-transclude-container-without-future><circle cx="2" cy="2" r="20"></circle></svg-custom-transclude-container></div>
从http://plnkr.co/edit/meRZylSgNWXhBVqP1Pa7?p=preview可以看出,带futureParentElement
的是部分圆,没有的不是。 DOM 的结构看起来是一样的。然而 Chrome 似乎报告说第二个 circle
元素不是 SVG 节点,而是一个普通的 HTML 节点。
因此,无论 futureParentElement
实际上在幕后做什么,它似乎都确保嵌入的 SVG 内容最终被浏览器作为 SVG 处理。
在 angular documentation for the compile service (starting at line 412) 中有对传递到指令的链接函数的 transclude 函数的描述。
相关部分为:
function([scope], cloneLinkingFn, futureParentElement)
其中(第 212 行):
futureParentElement
: defines the parent to which thecloneLinkingFn
will add the cloned elements.
default:
$element.parent()
resp.$element
fortransclude:'element'
resp.transclude:true
.only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements) and when the
cloneLinkinFn
is passed, as those elements need to created and cloned in a special way when they are defined outside their usual containers (e.g. like<svg>
).See also the
directive.templateNamespace
property.
然而,我没有看到 futureParentElement
的意义。它说
defines the parent to which the cloneLinkingFn will add the cloned elements.
但是你在 cloneLinkingFn
中这样做:
transclude(scope, function (clone) {
some_element.append(clone);
});
而且如果不首先定义克隆函数,就不能使用 transclude 函数。
usage/a futureParentElement
的正确用法是什么?
可以通过查看 git blame of compile.js
: the commit that added futureParentElement
is https://github.com/angular/angular.js/commit/ffbd276d6def6ff35bfdb30553346e985f4a0de6
在提交中有一个测试指令的测试svgCustomTranscludeContainer
directive('svgCustomTranscludeContainer', function() {
return {
template: '<svg width="400" height="400"></svg>',
transclude: true,
link: function(scope, element, attr, ctrls, $transclude) {
var futureParent = element.children().eq(0);
$transclude(function(clone) {
futureParent.append(clone);
}, futureParent);
}
};
});
通过测试 html <svg-custom-transclude-container><circle cx="2" cy="2" r="1"></circle>
的编译行为:
it('should handle directives with templates that manually add the transclude further down', inject(function() {
element = jqLite('<div><svg-custom-transclude-container>' +
'<circle cx="2" cy="2" r="1"></circle></svg-custom-transclude-container>' +
'</div>');
$compile(element.contents())($rootScope);
document.body.appendChild(element[0]);
var circle = element.find('circle');
assertIsValidSvgCircle(circle[0]);
}));
因此,如果您使用指令创建 SVG 图像,其模板将嵌入的 SVG 内容包装在 <svg> ... </svg>
标记中,那么该 SVG 图像将无效(根据某种定义),如果您不要将正确的 futureParentElement
传递给 $transclude
.
为了了解无效的实际含义,除了源代码中的测试之外,我基于单元测试中的指令创建了 2 个指令,并使用它们尝试创建具有部分内容的 SVG 图像圆圈。一个使用 futureParentElement
:
<div><svg-custom-transclude-container-with-future><circle cx="1" cy="2" r="20"></circle></svg-custom-transclude-container></div>
还有一个相同但不同的:
<div><svg-custom-transclude-container-without-future><circle cx="2" cy="2" r="20"></circle></svg-custom-transclude-container></div>
从http://plnkr.co/edit/meRZylSgNWXhBVqP1Pa7?p=preview可以看出,带futureParentElement
的是部分圆,没有的不是。 DOM 的结构看起来是一样的。然而 Chrome 似乎报告说第二个 circle
元素不是 SVG 节点,而是一个普通的 HTML 节点。
因此,无论 futureParentElement
实际上在幕后做什么,它似乎都确保嵌入的 SVG 内容最终被浏览器作为 SVG 处理。