big change: shallow render

With this commit, component only render child
components if they have different props (shallow
equality). Otherwise, we trust the reactivity
system to make sure that all impacted components
are updated
This commit is contained in:
Géry Debongnie
2021-11-18 16:57:33 +01:00
parent 0e0ac5329a
commit dfead2836e
19 changed files with 198 additions and 113 deletions
+2 -2
View File
@@ -948,7 +948,7 @@ export class CodeGenerator {
let propString = propStr;
if (ast.dynamicProps) {
if (!props.length) {
propString = `${compileExpr(ast.dynamicProps)}`;
propString = `Object.assign({}, ${compileExpr(ast.dynamicProps)})`;
} else {
propString = `Object.assign({}, ${compileExpr(ast.dynamicProps)}, ${propStr})`;
}
@@ -1012,7 +1012,7 @@ export class CodeGenerator {
keyArg = `${ctx.tKeyExpr} + ${keyArg}`;
}
const blockArgs = `${expr}, ${propString}, ${keyArg}, node, ctx`;
let blockExpr = `component(${blockArgs})`;
let blockExpr = `component(${blockArgs}${hasSlot ? ", true" : ""})`;
if (Object.keys(extraArgs).length) {
this.shouldDefineAssign = true;
const content = Object.keys(extraArgs).map((k) => `${k}: ${extraArgs[k]}`);
+2
View File
@@ -1,6 +1,8 @@
import type { Env } from "../app/app";
import type { ComponentNode } from "./component_node";
export type Props = { [key: string]: any };
// -----------------------------------------------------------------------------
// Component Class
// -----------------------------------------------------------------------------
+18 -3
View File
@@ -1,6 +1,6 @@
import type { App, Env } from "../app/app";
import { BDom, VNode } from "../blockdom";
import { Component } from "./component";
import { Component, Props } from "./component";
import {
Fiber,
makeChildFiber,
@@ -15,12 +15,21 @@ import { applyDefaultProps } from "./props_validation";
import { STATUS } from "./status";
import { applyStyles } from "./style";
function arePropsDifferent(props1: Props, props2: Props): boolean {
for (let k in props1) {
if (props1[k] !== props2[k]) {
return true;
}
}
return false;
}
export function component(
name: string | typeof Component,
props: any,
key: string,
ctx: ComponentNode,
parent: any
parent: any,
hasSlots: boolean = false
): ComponentNode {
let node: any = ctx.children[key];
let isDynamic = typeof name !== "string";
@@ -39,7 +48,9 @@ export function component(
const parentFiber = ctx.fiber!;
if (node) {
node.updateAndRender(props, parentFiber);
if (hasSlots || arePropsDifferent(node.component.props, props)) {
node.updateAndRender(props, parentFiber);
}
} else {
// new component
let C;
@@ -241,6 +252,10 @@ export class ComponentNode<T extends typeof Component = typeof Component>
}
patch() {
if (!this.fiber) {
// component was not rendered => no need to do anything
return;
}
this.bdom!.patch(this!.fiber!.bdom!, false);
this.fiber!.appliedToDom = true;
this.fiber = null;