SVG に innerHTML shim (別名「innerSVG」) を使用すると、Jason More の洞察に満ちた回答に代わるものとして、このパズルの別のピースが提供されます。この innerHTML/innerSVG アプローチは、Jason の回答のような特別なコンパイル関数を必要としないため、よりエレガントだと思いますが、少なくとも 1 つの欠点があります。「replace: true」がディレクティブに設定されている場合は機能しません。(innerSVG アプローチについては、こちらで説明しています: Is there some innerHTML replacement in SVG/XML? )
// Inspiration for this derived from a shim known as "innerSVG" which adds
// an "innerHTML" attribute to SVGElement:
Object.defineProperty(SVGElement.prototype, 'innerHTML', {
get: function() {
// TBD!
},
set: function(markup) {
// 1. Remove all children
while (this.firstChild) {
this.removeChild(this.firstChild);
}
// 2. Parse the SVG
var doc = new DOMParser().parseFromString(
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">'
+ markup
+ '</svg>',
'application/xml'
);
// 3. Import the parsed SVG and grab the childNodes
var contents = this.ownerDocument.importNode(doc.documentElement, true).childNodes;
// 4. Append the childNodes to this node
// Note: the following for loop won't work because as items are appended,
// they are removed from contents (you'd end up with only every other
// element getting appended and the other half remaining still in the
// original document tree):
//for (var i = 0; i < contents.length; i++) {
// this.appendChild(contents[i]);
//}
while (contents.length) {
this.appendChild(contents[0]);
}
},
enumerable: false,
configurable: true
});
試すプランカーは次のとおりです。http://plnkr.co/edit/nEqfbbvpUCOVC1XbTKdQ?p=preview
これが機能する理由: SVG 要素は XML 名前空間http://www.w3.org/2000/svg内に存在するため、DOMParser() で解析するか、createElementNS() でインスタンス化する必要があります (どちらも名前空間を適切に設定できます。SVG を使用するこのプロセスが HTML と同じくらい簡単であればいいのですが、残念ながらそれらの DOM 構造は微妙に異なるため、独自の innerHTML shim を提供する必要があります。さて、これで「replace: true」も動作するようになれば、それは良いことです!
編集:appendChild() ループを更新して、ループの実行中に内容が変更される回避策にしました。