[IMP] portal: portal as a Directive

Before this commit, portal was a Component, now is a directive.
This commit also clean some unused code, and fix an issue on the clean
optimization when a portal is found in a condition or a loop.
This commit is contained in:
Jorge Pinna Puissant
2022-01-11 10:47:50 +01:00
committed by Aaron Bohy
parent c221721d7f
commit 90167c5436
11 changed files with 558 additions and 252 deletions
+11 -3
View File
@@ -47,7 +47,7 @@ const cache: { [key: string]: BlockType } = {};
* @param str
* @returns a new block type, that can build concrete blocks
*/
export function createBlock(str: string): BlockType {
export function createBlock(str: string, deepRemove: boolean = false): BlockType {
if (str in cache) {
return cache[str];
}
@@ -67,7 +67,7 @@ export function createBlock(str: string): BlockType {
// step 3: build the final block class
const template = tree.el as HTMLElement;
const Block = buildBlock(template, context);
const Block = buildBlock(template, context, deepRemove);
cache[str] = Block;
return Block;
}
@@ -422,7 +422,7 @@ function updateCtx(ctx: BlockCtx, tree: IntermediateTree) {
// building the concrete block class
// -----------------------------------------------------------------------------
function buildBlock(template: HTMLElement, ctx: BlockCtx): BlockType {
function buildBlock(template: HTMLElement, ctx: BlockCtx, deepRemove: boolean): BlockType {
let B = createBlockClass(template, ctx);
if (ctx.cbRefs.length) {
@@ -447,6 +447,14 @@ function buildBlock(template: HTMLElement, ctx: BlockCtx): BlockType {
}
};
B.prototype.beforeRemove = VMulti.prototype.beforeRemove;
if (deepRemove) {
const blockRemove = B.prototype.remove;
const vMultiRemove = VMulti.prototype.remove;
B.prototype.remove = function () {
blockRemove.call(this);
vMultiRemove.call(this);
};
}
return (data?: any[], children: (VNode | undefined)[] = []) => new B(data, children);
}
+7 -6
View File
@@ -17,9 +17,11 @@ class VList {
anchor: Node | undefined;
parentEl?: HTMLElement | undefined;
isOnlyChild?: boolean | undefined;
deepRemove: boolean;
constructor(children: VNode[]) {
constructor(children: VNode[], deepRemove: boolean) {
this.children = children;
this.deepRemove = deepRemove;
}
mount(parent: HTMLElement, afterNode: Node | null) {
@@ -75,7 +77,7 @@ class VList {
const parent = this.parentEl!;
// fast path: no new child => only remove
if (ch2.length === 0 && isOnlyChild) {
if (ch2.length === 0 && isOnlyChild && !this.deepRemove) {
if (withBeforeRemove) {
for (let i = 0, l = ch1.length; i < l; i++) {
beforeRemove.call(ch1[i]);
@@ -98,7 +100,6 @@ class VList {
let endVn2 = ch2[endIdx2];
let mapping: any = undefined;
// let noFullRemove = this.hasNoComponent;
while (startIdx1 <= endIdx1 && startIdx2 <= endIdx2) {
// -------------------------------------------------------------------
@@ -202,7 +203,7 @@ class VList {
remove() {
const { parentEl, anchor } = this;
if (this.isOnlyChild) {
if (this.isOnlyChild && !this.deepRemove) {
nodeSetTextContent.call(parentEl, "");
} else {
const children = this.children;
@@ -227,8 +228,8 @@ class VList {
}
}
export function list(children: VNode[]): VNode<VList> {
return new VList(children);
export function list(children: VNode[], deepRemove = false): VNode<VList> {
return new VList(children, deepRemove);
}
function createMapping(ch1: any[], startIdx1: number, endIdx2: number): { [key: string]: any } {
+6 -4
View File
@@ -15,9 +15,11 @@ export class VMulti {
anchors?: Node[] | undefined;
parentEl?: HTMLElement | undefined;
isOnlyChild?: boolean | undefined;
deepRemove: boolean;
constructor(children: (VNode | undefined)[]) {
constructor(children: (VNode | undefined)[], deepRemove: boolean) {
this.children = children;
this.deepRemove = deepRemove;
}
mount(parent: HTMLElement, afterNode: Node | null) {
@@ -103,7 +105,7 @@ export class VMulti {
remove() {
const parentEl = this.parentEl;
if (this.isOnlyChild) {
if (this.isOnlyChild && !this.deepRemove) {
nodeSetTextContent.call(parentEl, "");
} else {
const children = this.children;
@@ -129,6 +131,6 @@ export class VMulti {
}
}
export function multi(children: (VNode | undefined)[]): VNode<VMulti> {
return new VMulti(children);
export function multi(children: (VNode | undefined)[], deepRemove = false): VNode<VMulti> {
return new VMulti(children, deepRemove);
}