Skip to content

Commit

Permalink
feat: VActions
Browse files Browse the repository at this point in the history
  • Loading branch information
aidenybai committed Jun 17, 2021
1 parent b9ea08f commit 68e5411
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 13 deletions.
6 changes: 3 additions & 3 deletions src/m.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { VElement, VFlags, VNode, VProps } from './structs';
* @param {VElement} vnode - SVG VNode
* @returns {VElement}
*/
/* istanbul ignore next */
export const svg = (vnode: VElement): VElement => {
if (!vnode.props) vnode.props = {};
ns(vnode.tag, vnode.props, vnode.children);
Expand Down Expand Up @@ -47,8 +46,9 @@ export const className = (classObject: Record<string, boolean>): string => {
/**
* Helper method for creating a VNode
* @param {string} tag - The tagName of an HTMLElement
* @param {VProps} props - DOM properties and attributes of an HTMLElement
* @param {VNode[]} children - Children of an HTMLElement
* @param {VProps=} props - DOM properties and attributes of an HTMLElement
* @param {VNode[]=} children - Children of an HTMLElement
* @param {VFlags=} flag - Compiler flag for VNode
* @returns {VElement}
*/
export const m = (tag: string, props?: VProps, children?: VNode[], flag?: VFlags): VElement => {
Expand Down
57 changes: 47 additions & 10 deletions src/patch.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { OLD_VNODE_FIELD } from './constants';
import { createElement } from './createElement';
import { VElement, VFlags, VNode, VProps } from './structs';
import { VActions, VElement, VFlags, VNode, VProps } from './structs';

/**
* Diffs two VNode props and modifies the DOM node based on the necessary changes
Expand Down Expand Up @@ -32,12 +32,12 @@ export const patchProps = (el: HTMLElement, oldProps: VProps, newProps: VProps):
/**
* Diffs two VNode children and modifies the DOM node based on the necessary changes
* @param {HTMLElement} el - Target element to be modified
* @param {VNode[]|undefined} oldVNodeChildren - Old VNode children
* @param {VNode[]|undefined} newVNodeChildren - New VNode children
* @param {VNode[]} oldVNodeChildren - Old VNode children
* @param {VNode[]} newVNodeChildren - New VNode children
*/
export const patchChildren = (
el: HTMLElement,
oldVNodeChildren: VNode[] | undefined,
oldVNodeChildren: VNode[],
newVNodeChildren: VNode[],
): void => {
const childNodes = [...el.childNodes];
Expand Down Expand Up @@ -91,7 +91,6 @@ export const patch = (
(!(<VElement>oldVNode)?.key && !(<VElement>newVNode)?.key) ||
(<VElement>oldVNode)?.key !== (<VElement>newVNode)?.key
) {
/* istanbul ignore if */
if (
(<VElement>oldVNode)?.tag !== (<VElement>newVNode)?.tag &&
!(<VElement>newVNode).children &&
Expand All @@ -105,17 +104,55 @@ export const patch = (
if (oldVNode && !(el instanceof Text)) {
patchProps(el, (<VElement>oldVNode).props || {}, (<VElement>newVNode).props || {});

/* istanbul ignore next */
switch (<VFlags>(<VElement>newVNode).flag) {
case VFlags.NO_CHILDREN:
case VFlags.NO_CHILDREN: {
el.textContent = '';
break;
case VFlags.ONLY_TEXT_CHILDREN:
}
case VFlags.ONLY_TEXT_CHILDREN: {
el.textContent = <string>(<VElement>newVNode).children!.join('');
break;
default:
patchChildren(el, (<VElement>oldVNode).children, (<VElement>newVNode).children!);
}
case VFlags.ANY_CHILDREN:
default: {
const [action, numberOfNodes] = (<VElement>newVNode).action ?? [VActions.ANY_ACTION, 0];
switch (action) {
case VActions.INSERT_TOP: {
for (let i = numberOfNodes - 1; i >= 0; --i) {
el.insertBefore(createElement((<VElement>newVNode).children![i]), el.firstChild);
}
break;
}
case VActions.INSERT_BOTTOM: {
for (let i = 0; i < numberOfNodes; i++) {
el.appendChild(createElement((<VElement>newVNode).children![i]));
}
break;
}
case VActions.DELETE_TOP: {
for (let i = numberOfNodes - 1; i >= 0; --i) {
el.removeChild(el.firstChild!);
}
break;
}
case VActions.DELETE_BOTTOM: {
for (let i = 0; i < numberOfNodes; i++) {
el.removeChild(el.lastChild!);
}
break;
}
case VActions.ANY_ACTION:
default: {
patchChildren(
el,
(<VElement>oldVNode).children || [],
(<VElement>newVNode).children!,
);
break;
}
}
break;
}
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/structs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,19 @@ export interface VElement {
children?: VNode[];
key?: string;
flag?: VFlags;
action?: [VActions, number]; // [Action, Number of nodes]
}

export enum VFlags {
NO_CHILDREN = 0,
ONLY_TEXT_CHILDREN = 1,
ANY_CHILDREN = 2,
}

export enum VActions {
INSERT_TOP = 0,
INSERT_BOTTOM = 1,
DELETE_TOP = 2,
DELETE_BOTTOM = 3,
ANY_ACTION = 4,
}

0 comments on commit 68e5411

Please sign in to comment.