diff --git a/apps/demo/src/components/counter/index.ts b/apps/demo/src/components/counter/index.ts
index c68f12e..1c565e4 100644
--- a/apps/demo/src/components/counter/index.ts
+++ b/apps/demo/src/components/counter/index.ts
@@ -1,12 +1,26 @@
-import { render, useStyles, useRef, useState, useEffect } from "extreme";
+import {
+ useStyles,
+ useRef,
+ useState,
+ useEffect,
+ createComponent,
+ useMount,
+} from "extreme";
import styles from "./index.css?raw";
import template from "./index.html?raw";
-export const Counter = (element: HTMLElement) => {
- useStyles(styles);
+export const Counter = createComponent("Counter", () => {
const resetRef = useRef();
const [count, setCount] = useState(0);
const [title, setTitle] = useState(`
`);
+ useStyles(styles);
+
+ useMount(() => {
+ resetRef()?.addEventListener("click", () => {
+ setCount(0);
+ setTitle("the form is not submit");
+ });
+ });
const decrement = () => {
setCount(count() - 1);
@@ -18,10 +32,19 @@ export const Counter = (element: HTMLElement) => {
setTitle("submit success");
};
- const base = render(element, template, {
+ count((newV) => {
+ console.log("newV", newV);
+ });
+
+ useEffect(() => {
+ console.log("count&title", count(), title());
+ }, [count, title]);
+
+ return {
+ template,
state: {
count,
- title
+ title,
},
ref: {
resetRef,
@@ -31,20 +54,5 @@ export const Counter = (element: HTMLElement) => {
increment,
handleSubmit: submit,
},
- });
-
- count((newV) => {
- console.log("newV", newV);
- });
-
- useEffect(() => {
- console.log("count&title", count(), title());
- }, [count, title]);
-
- resetRef()?.addEventListener("click", () => {
- setCount(0);
- setTitle("the form is not submit");
- });
-
- return base;
-};
+ };
+});
diff --git a/apps/demo/src/components/custom-component/index.ts b/apps/demo/src/components/custom-component/index.ts
index c0c9e3d..3c322ea 100644
--- a/apps/demo/src/components/custom-component/index.ts
+++ b/apps/demo/src/components/custom-component/index.ts
@@ -1,35 +1,38 @@
-import { GetState, useRef, render } from "extreme";
+import { GetState, useRef, createComponent } from "extreme";
import template from "./index.html?raw";
-export const CustomComponent = (
- element: HTMLElement,
- props: {
- open?: boolean | GetState;
- } = {}
-) => {
- const defaultData = [
- {
- src: "https://img.alicdn.com/imgextra/i4/O1CN01QYQ1QI1CZQYQ1QYQI_!!6000000001382-2-tps-200-200.png",
- content: "这是一段描述1,但是我是新的默认数据",
- title: "这是一段标题1",
- key: 1,
- },
- {
- src: "https://img.alicdn.com/imgextra/i4/O1CN01QYQ1QI1CZQYQ1QYQI_!!6000000001382-2-tps-200-200.png",
- content: "这是一段描述2",
- title: "这是一段标题2",
- key: 2,
- },
- ];
- const divRef = useRef();
+export const CustomComponent = createComponent(
+ "CustomComponent",
+ (
+ props: {
+ open?: boolean | GetState;
+ } = {}
+ ) => {
+ const defaultData = [
+ {
+ src: "https://img.alicdn.com/imgextra/i4/O1CN01QYQ1QI1CZQYQ1QYQI_!!6000000001382-2-tps-200-200.png",
+ content: "这是一段描述1,但是我是新的默认数据",
+ title: "这是一段标题1",
+ key: 1,
+ },
+ {
+ src: "https://img.alicdn.com/imgextra/i4/O1CN01QYQ1QI1CZQYQ1QYQI_!!6000000001382-2-tps-200-200.png",
+ content: "这是一段描述2",
+ title: "这是一段标题2",
+ key: 2,
+ },
+ ];
+ const divRef = useRef();
- return render(element, template, {
- state: {
- defaultData,
- open: props.open,
- },
- ref: {
- divRef,
- },
- });
-};
+ return {
+ template,
+ state: {
+ defaultData,
+ open: props.open,
+ },
+ ref: {
+ divRef,
+ },
+ };
+ }
+);
diff --git a/apps/demo/src/components/list/index.ts b/apps/demo/src/components/list/index.ts
index d197ffe..287e697 100644
--- a/apps/demo/src/components/list/index.ts
+++ b/apps/demo/src/components/list/index.ts
@@ -1,4 +1,4 @@
-import { useStyles, useState, useRef, render } from "extreme";
+import { useStyles, useState, useRef, createComponent } from "extreme";
import styles from "./index.css?raw";
import template from "./index.html?raw";
@@ -16,92 +16,94 @@ const defaultData = [
key: 2,
},
];
-export const List = (
- element: HTMLElement,
- props: {
- defaultData?: typeof defaultData;
- } = {}
-) => {
- useStyles(styles);
- const [data, setData] = useState(props.defaultData || defaultData);
- const listRef = useRef();
+export const List = createComponent(
+ "List",
+ (
+ props: {
+ defaultData?: typeof defaultData;
+ } = {}
+ ) => {
+ useStyles(styles);
- const handleClear = () => {
- setData([]);
- };
- const handleReset = () => {
- setData(defaultData);
- };
- const handleAdd = () => {
- const source = data();
+ const [data, setData] = useState(props.defaultData || defaultData);
+ const listRef = useRef();
- const newKey =
- source.length > 0 ? Math.max(...source.map((item) => item.key)) + 1 : 1;
- setData([
- ...data(),
- {
- src: "https://img.alicdn.com/imgextra/i4/O1CN01QYQ1QI1CZQYQ1QYQI_!!6000000001382-2-tps-200-200.png",
- content: "这是一段描述" + newKey,
- title: "这是一段标题" + newKey,
- key: newKey,
- },
- ]);
+ const handleClear = () => {
+ setData([]);
+ };
+ const handleReset = () => {
+ setData(defaultData);
+ };
+ const handleAdd = () => {
+ const source = data();
- const listContainer = listRef();
- if (listContainer) {
- listContainer.scrollTop = listContainer.scrollHeight;
- }
- };
- const handleMove = () => {
- setData([
- {
- src: "https://img.alicdn.com/imgextra/i4/O1CN01QYQ1QI1CZQYQ1QYQI_!!6000000001382-2-tps-200-200.png",
- content: "这是一段描述",
- title: "这是一段标题",
- key: 2,
- },
- {
- src: "https://img.alicdn.com/imgextra/i4/O1CN01QYQ1QI1CZQYQ1QYQI_!!6000000001382-2-tps-200-200.png",
- content: "这是一段描述Move+Update",
- title: "这是一段标题Move+Update",
- key: 1,
+ const newKey =
+ source.length > 0 ? Math.max(...source.map((item) => item.key)) + 1 : 1;
+ setData([
+ ...data(),
+ {
+ src: "https://img.alicdn.com/imgextra/i4/O1CN01QYQ1QI1CZQYQ1QYQI_!!6000000001382-2-tps-200-200.png",
+ content: "这是一段描述" + newKey,
+ title: "这是一段标题" + newKey,
+ key: newKey,
+ },
+ ]);
+
+ const listContainer = listRef();
+ if (listContainer) {
+ listContainer.scrollTop = listContainer.scrollHeight;
+ }
+ };
+ const handleMove = () => {
+ setData([
+ {
+ src: "https://img.alicdn.com/imgextra/i4/O1CN01QYQ1QI1CZQYQ1QYQI_!!6000000001382-2-tps-200-200.png",
+ content: "这是一段描述",
+ title: "这是一段标题",
+ key: 2,
+ },
+ {
+ src: "https://img.alicdn.com/imgextra/i4/O1CN01QYQ1QI1CZQYQ1QYQI_!!6000000001382-2-tps-200-200.png",
+ content: "这是一段描述Move+Update",
+ title: "这是一段标题Move+Update",
+ key: 1,
+ },
+ ]);
+ };
+ const handleUpdate = () => {
+ setData([
+ {
+ src: "https://img.alicdn.com/imgextra/i4/O1CN01QYQ1QI1CZQYQ1QYQI_!!6000000001382-2-tps-200-200.png",
+ content: "这是一段描述[key没有变化]",
+ title: "这是一段标题",
+ key: 1,
+ },
+ {
+ src: "https://img.alicdn.com/imgextra/i4/O1CN01QYQ1QI1CZQYQ1QYQI_!!6000000001382-2-tps-200-200.png",
+ content: "这是一段描述",
+ title: "这是一段标题",
+ key: 2,
+ },
+ ]);
+ };
+
+ return {
+ template,
+ state: {
+ items: data,
+ showReset: () => data().length > 0,
},
- ]);
- };
- const handleUpdate = () => {
- setData([
- {
- src: "https://img.alicdn.com/imgextra/i4/O1CN01QYQ1QI1CZQYQ1QYQI_!!6000000001382-2-tps-200-200.png",
- content: "这是一段描述[key没有变化]",
- title: "这是一段标题",
- key: 1,
+ methods: {
+ handleClear,
+ handleReset,
+ handleAdd,
+ handleMove,
+ handleUpdate,
},
- {
- src: "https://img.alicdn.com/imgextra/i4/O1CN01QYQ1QI1CZQYQ1QYQI_!!6000000001382-2-tps-200-200.png",
- content: "这是一段描述",
- title: "这是一段标题",
- key: 2,
+ ref: {
+ listRef,
},
- ]);
- };
-
- const list = render(element, template, {
- state: {
- items: data,
- showReset: () => data().length > 0,
- },
- methods: {
- handleClear,
- handleReset,
- handleAdd,
- handleMove,
- handleUpdate,
- },
- ref: {
- listRef,
- },
- });
-
- return list;
-};
+ };
+ }
+);
diff --git a/apps/demo/src/main.ts b/apps/demo/src/main.ts
index 53f95c0..4f4acb4 100644
--- a/apps/demo/src/main.ts
+++ b/apps/demo/src/main.ts
@@ -1,16 +1,7 @@
import "./style.css";
-import { Counter, List, CustomComponent } from "./components";
-import { App, Topbar, Content, Demo } from "./modules";
-
-import { extreme } from "extreme";
-
-extreme.use({
- Counter,
- List,
- CustomComponent,
- Topbar,
- Content,
-});
+import { App, Demo } from "./modules";
+export * from "./components"
+export * from "./modules"
const handleHashChange = () => {
if (window.location.hash.match(/#\/demo/)) {
diff --git a/apps/demo/src/modules/content/index.ts b/apps/demo/src/modules/content/index.ts
index 9be859f..3b3e4a5 100644
--- a/apps/demo/src/modules/content/index.ts
+++ b/apps/demo/src/modules/content/index.ts
@@ -1,6 +1,6 @@
-import { render } from "extreme";
+import { createComponent } from "extreme";
import template from "./index.html?raw";
-export const Content = (element: HTMLElement) => {
- return render(element, template);
-};
+export const Content = createComponent("Content", () => {
+ return { template };
+});
diff --git a/apps/demo/src/modules/top-bar/index.ts b/apps/demo/src/modules/top-bar/index.ts
index 090ba57..6ef1287 100644
--- a/apps/demo/src/modules/top-bar/index.ts
+++ b/apps/demo/src/modules/top-bar/index.ts
@@ -1,10 +1,11 @@
-import { render } from "extreme";
+import { createComponent } from "extreme";
import template from "./index.html?raw";
-export const Topbar = (element: HTMLElement) => {
- return render(element, template, {
+export const Topbar = createComponent("Topbar", () => {
+ return {
+ template,
state: {
title: "topbar",
},
- });
-};
+ };
+});
diff --git a/packages/extreme/src/core/extreme.ts b/packages/extreme/src/core/extreme.ts
index 7caebde..d02b517 100644
--- a/packages/extreme/src/core/extreme.ts
+++ b/packages/extreme/src/core/extreme.ts
@@ -31,9 +31,10 @@ export const createComponent = (name: string, component: ExtremeRenderFn) => {
replace: boolean = true
) => {
const result = component(props);
- render(element, result.template, result, replace);
+ const ele = render(element, result.template, result, replace);
currentCell.mount?.();
resetCurrentCell();
+ return ele;
};
fn.displayName = name;
if (extreme.store[name]) {
diff --git a/packages/extreme/src/core/render.ts b/packages/extreme/src/core/render.ts
index afc4ef7..bcd1cf9 100644
--- a/packages/extreme/src/core/render.ts
+++ b/packages/extreme/src/core/render.ts
@@ -72,8 +72,7 @@ export function render(
{
const usageDomSet = new Set();
template.replace(/{{(.*?)}}/g, (_, _key, start) => {
- const dom = findDomStr(start, template);
- usageDomSet.add(dom);
+ usageDomSet.add(findDomStr(start, template));
return _;
});
usageDomSet.forEach((dom) => {
@@ -94,8 +93,7 @@ export function render(
{
template = template.replace(/@(.*?)}}"/g, (_, key, start) => {
const [methodName, funcName] = key.split(`=\"{{`);
- const dom = findDomStr(start, template);
- addMethodTask(methodName, funcName, dom);
+ addMethodTask(methodName, funcName, findDomStr(start, template));
return "";
});
}
@@ -112,11 +110,10 @@ export function render(
const id = getDomID(baseDom)!;
const addTask = (value?: boolean | null) => {
- const task = [
+ ifTasks.push([
baseDom,
value ? dom : ``,
- ] as [string, string];
- ifTasks.push(task);
+ ] as [string, string]);
};
if (typeof value === "function") {
@@ -168,7 +165,6 @@ export function render(
return _;
});
for (const [baseDom, newDom] of ifTasks) {
- console.log("baseDom", baseDom, newDom);
template = template.replace(baseDom, newDom);
}
@@ -361,8 +357,7 @@ export function render(
const value = getValue(state, key);
if (typeof value === "function") {
- const dom = findDomStr(start, template);
- stateSet.add(dom);
+ stateSet.add(findDomStr(start, template));
return source;
}
return encodeValue(value);
@@ -378,10 +373,7 @@ export function render(
return ref[key] as unknown as string;
}
const value = getValue(state, key);
- if (typeof value === "function") {
- return source;
- }
- return encodeValue(value);
+ return typeof value === "function" ? source : encodeValue(value);
});
const [baseDomStr, id] = addDomID(sourceDomStr, getRandomID);
const newDomStr = baseDomStr.replace(
@@ -398,23 +390,22 @@ export function render(
const dom = document.getElementById(id);
if (!dom) return;
const newValue = encodeValue(value());
- if (analyzeUpdateKey.type === "textContent") {
- dom.textContent = newValue;
- return;
- }
- if (analyzeUpdateKey.type === "attr") {
- dom.setAttribute(analyzeUpdateKey.key, newValue);
- return;
- }
- if (analyzeUpdateKey.type === "textNode") {
- dom.childNodes[analyzeUpdateKey.key].textContent =
- analyzeUpdateKey.content.replace(/{{(.*?)}}/g, (_, key) => {
- const value = getValue(state, key);
- return encodeValue(
- typeof value === "function" ? value() : value
- );
- });
- return;
+ switch (analyzeUpdateKey.type) {
+ case "textContent":
+ dom.textContent = newValue;
+ break;
+ case "attr":
+ dom.setAttribute(analyzeUpdateKey.key, newValue);
+ break;
+ case "textNode":
+ dom.childNodes[analyzeUpdateKey.key].textContent =
+ analyzeUpdateKey.content.replace(/{{(.*?)}}/g, (_, key) => {
+ const value = getValue(state, key);
+ return encodeValue(
+ typeof value === "function" ? value() : value
+ );
+ });
+ break;
}
};
setCurrentListener(rerenderDom);
@@ -422,7 +413,6 @@ export function render(
setCurrentListener(null);
return newValue;
}
-
return encodeValue(value);
}
);
diff --git a/packages/extreme/src/hooks/useEffect.ts b/packages/extreme/src/hooks/useEffect.ts
index a1affed..800bcdf 100644
--- a/packages/extreme/src/hooks/useEffect.ts
+++ b/packages/extreme/src/hooks/useEffect.ts
@@ -3,7 +3,5 @@ import type { GetState } from "./useState";
import { idleCallback } from "./useState";
export const useEffect = (fn: Function, deps: GetState[]) => {
- for (const dep of deps) {
- dep((v) => idleCallback(() => fn(v)));
- }
+ for (const dep of deps) dep((v) => idleCallback(() => fn(v)))
};