カテゴリー
【Angular基礎講座】レンダリング後のhtmlの無駄にラップされている要素を無理やり剥がしてみる
※ 当ページには【広告/PR】を含む場合があります。
2019/09/19
2022/08/10
Renderer2
Renderer2
Renderer2
検証 - 通常のレンダリング後のhtml出力
import { Component } from '@angular/core';
@Component({
selector: 'app-my-grandchild-comp',
template: `<div>my-grandchild</div>`
})
export class MyGrandChildComponent {}
@Component({
selector: 'app-my-child-comp',
template: `
<div>
my-child
<app-my-grandchild-comp></app-my-grandchild-comp>
</div>
`
})
export class MyChildComponent {}
@Component({
selector: 'app-myself-comp',
template: `
<div>
me
<app-my-child-comp></app-my-child-comp>
</div>
`
})
export class MyselfComponent {}
@Component({
selector: 'app-my-parent-comp',
template: `
<div>
my-parent
<app-myself-comp></app-myself-comp>
</div>
`
})
export class MyParentComponent {}
@Component({
selector: 'app-my-grandparent-comp',
template: `
<div>
my-grandparent
<app-my-parent-comp></app-my-parent-comp>
</div>
`
})
export class MyGrandParentComponent {}
<app-my-grandparent-comp></app-my-grandparent-comp>
<div>
my-grandparent
<div>
my-parent
<div>
me
<div>
my-child
<div>
my-grandchild
</div>
</div>
</div>
</div>
</div>
<table>
<thead>, <tbody>, <tfoot>
<tr>
Renderer2の基本
Renderer2
MyselfComponent
<app-myself-comp>
import {
Directive, AfterViewInit, ElementRef, Renderer2
} from '@angular/core';
@Directive({
selector: '[appDomManipulator]'
})
export class DomManipulatorDirective implements AfterViewInit {
constructor(
private el: ElementRef,
private renderer: Renderer2
) { }
ngAfterViewInit() {
const itsMe = this.el.nativeElement; // 自分本体(この場合<app-myself-comp>)
const parentsDiv = this.renderer.parentNode(itsMe); // <app-parent-comp>内の<div>
const parent = this.renderer.parentNode(parentsDiv); // <app-parent-comp>本体
const grandparentsDiv = this.renderer.parentNode(parent); // <app-grandparent-comp>内の<div>
const grandparent = this.renderer.parentNode(grandparentsDiv); // <app-grandparent-comp>本体
const myDiv = itsMe.childNodes[0]; // 自分の中の<div>
const child = myDiv.childNodes[1]; // <app-child-comp>本体
const childsDiv = child.childNodes[0]; // <app-child-comp>内の<div>
const grandchild = childsDiv.childNodes[1]; // <app-grandchild-comp>本体
console.log(grandparent);
console.log(parent);
console.log(itsMe);
console.log(child);
console.log(grandchild);
}
}
MyParentComponent
<app-myself-comp>
...
@Component({
selector: 'app-my-parent-comp',
template: `
<div>
my-parent
<app-myself-comp appDomManipulator></app-myself-comp>
</div>
`
})
export class MyParentComponent {}
...
<app-myself-comp>
Renderer2
parentNode
parentNode
childNodes
insertBeforeで親子の縁を切る
Renderer2
Method:
insertBefore(parent: any, newChild: any, refChild: any): void
Parameters:
parent:
新しく親にしたいDOMノード
newChild:
新たに子ノードとして移動したいDOMノード
refChild:
もともと親だったDOMノード
insertBefore(親の親ノード, 子ノード, 親ノード)
import {
Directive, AfterViewInit, ElementRef, Renderer2
} from '@angular/core';
@Directive({
selector: '[appUnwrapDom]'
})
export class UnwrapDomDirective implements AfterViewInit {
constructor(
private el: ElementRef,
private renderer: Renderer2
) { }
ngAfterViewInit() {
const myDiv = this.el.nativeElement; // <app-***>の中身(=この場合指定した<div>)
const parent = this.renderer.parentNode(myDiv); // 親要素の<app-*****>
const superparent = this.renderer.parentNode(parent); // 親要素の一つ上
this.renderer.insertBefore(superparent, myDiv, parent);
}
}
<div>...</div>
<app-***>
import { Component } from '@angular/core';
@Component({
selector: 'app-my-grandchild-comp',
template: `<div appUnwrapDom>my-grandchild</div>`
})
export class MyGrandChildComponent {}
@Component({
selector: 'app-my-child-comp',
template: `
<div appUnwrapDom>
my-child
<app-my-grandchild-comp></app-my-grandchild-comp>
</div>
`
})
export class MyChildComponent {}
@Component({
selector: 'app-myself-comp',
template: `
<div appUnwrapDom>
me
<app-my-child-comp></app-my-child-comp>
</div>
`
})
export class MyselfComponent {}
@Component({
selector: 'app-my-parent-comp',
template: `
<div appUnwrapDom>
my-parent
<app-myself-comp></app-myself-comp>
</div>
`
})
export class MyParentComponent {}
@Component({
selector: 'app-my-grandparent-comp',
template: `
<div appUnwrapDom>
my-grandparent
<app-my-parent-comp></app-my-parent-comp>
</div>
`
})
export class MyGrandParentComponent {}
不要なDOMを削除するremoveChild()メソッド
<app-***>
Renderer2
insertBefore
removeChild(消したいノードの親ノード, 消したいノード)
unwrap-dom.directive.ts
import {
Directive, AfterViewInit, ElementRef, Renderer2
} from '@angular/core';
@Directive({
selector: '[appUnwrapDom]'
})
export class UnwrapDomDirective implements AfterViewInit {
constructor(
private el: ElementRef,
private renderer: Renderer2
) { }
ngAfterViewInit() {
const myDiv = this.el.nativeElement; // <app-***>の中身(=この場合指定した<div>)
const parent = this.renderer.parentNode(myDiv); // 親要素の<app-*****>
const superparent = this.renderer.parentNode(parent); // 親要素の一つ上
this.renderer.insertBefore(superparent, myDiv, parent);
// 残留した<app-***>を消去
this.renderer.removeChild(superparent, parent);
}
}
まとめ
<ng-content></ng-content>
ngIf, ngIf, ngSwitch,...
<ng-content>
Renderer2
参考
Renderer2
Renderer3
Ivy
Renderer2
Ivy
Renderer2
AfterViewInit
Ivy
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー