inula/packages/inula-next/src/MutableNode/ExpNode.js

87 lines
2.6 KiB
JavaScript

import { DLNodeType } from '../DLNode';
import { FlatNode } from './FlatNode';
import { DLStore, cached } from '../store';
export class ExpNode extends FlatNode {
/**
* @brief Constructor, Exp type, accept a function that returns a list of nodes
* @param nodesFunc
*/
constructor(value, deps) {
super(DLNodeType.Exp);
this.initUnmountStore();
this._$nodes = ExpNode.formatNodes(value);
this.setUnmountFuncs();
this.deps = this.parseDeps(deps);
// ---- Add to the global UnmountStore
ExpNode.addWillUnmount(this, this.runWillUnmount.bind(this));
ExpNode.addDidUnmount(this, this.runDidUnmount.bind(this));
}
parseDeps(deps) {
return deps.map(dep => {
// ---- CompNode
if (dep?.prototype?._$init) return dep.toString();
// ---- SnippetNode
if (dep?.propViewFunc) return dep.propViewFunc.toString();
return dep;
});
}
cache(deps) {
if (!deps || !deps.length) return false;
deps = this.parseDeps(deps);
if (cached(deps, this.deps)) return true;
this.deps = deps;
return false;
}
/**
* @brief Generate new nodes and replace the old nodes
*/
update(valueFunc, deps) {
if (this.cache(deps)) return;
this.removeNodes(this._$nodes);
const newNodes = this.geneNewNodesInEnv(() => ExpNode.formatNodes(valueFunc()));
if (newNodes.length === 0) {
this._$nodes = [];
return;
}
// ---- Add new nodes
const parentEl = this._$parentEl;
const flowIndex = ExpNode.getFlowIndexFromNodes(parentEl._$nodes, this);
const nextSibling = parentEl.childNodes[flowIndex];
ExpNode.appendNodesWithSibling(newNodes, parentEl, nextSibling);
ExpNode.runDidMount();
this._$nodes = newNodes;
}
/**
* @brief Format the nodes
* @param nodes
* @returns New nodes
*/
static formatNodes(nodes) {
if (!Array.isArray(nodes)) nodes = [nodes];
return (
nodes
// ---- Flatten the nodes
.flat(1)
// ---- Filter out empty nodes
.filter(node => node !== undefined && node !== null && typeof node !== 'boolean')
.map(node => {
// ---- If the node is a string, number or bigint, convert it to a text node
if (typeof node === 'string' || typeof node === 'number' || typeof node === 'bigint') {
return DLStore.document.createTextNode(`${node}`);
}
// ---- If the node has PropView, call it to get the view
if ('propViewFunc' in node) return node.build();
return node;
})
// ---- Flatten the nodes again
.flat(1)
);
}
}