From b0de6033b54dc4d8d16b8635ba7fce3872e063fd Mon Sep 17 00:00:00 2001 From: unknown <1533540012@qq.com> Date: Wed, 18 Oct 2023 18:39:49 +0800 Subject: [PATCH] emmm --- demo/app.jsx | 222 ++++++++++++++++++++++++-- demo/index.html => index.html | 2 +- src/index.js | 30 ++-- demo/vite.config.js => vite.config.js | 0 4 files changed, 222 insertions(+), 32 deletions(-) rename demo/index.html => index.html (81%) rename demo/vite.config.js => vite.config.js (100%) diff --git a/demo/app.jsx b/demo/app.jsx index 33bc02d..0bb69c7 100644 --- a/demo/app.jsx +++ b/demo/app.jsx @@ -1,16 +1,208 @@ -import { h, render, useState, Fragment, useEffect } from './fre' - - -const App = () => { - useEffect(()=>{ - console.log(123) - },[]) - const [count, setCount] = useState(0) - console.log(count) - return <> - - +import { h, render, useReducer, useCallback } from "../src/index" + +function random(max) { + return Math.round(Math.random() * 1000) % max +} + +const A = [ + "pretty", + "large", + "big", + "small", + "tall", + "short", + "long", + "handsome", + "plain", + "quaint", + "clean", + "elegant", + "easy", + "angry", + "crazy", + "helpful", + "mushy", + "odd", + "unsightly", + "adorable", + "important", + "inexpensive", + "cheap", + "expensive", + "fancy", +] +const C = [ + "red", + "yellow", + "blue", + "green", + "pink", + "brown", + "purple", + "brown", + "white", + "black", + "orange", +] +const N = [ + "table", + "chair", + "house", + "bbq", + "desk", + "car", + "pony", + "cookie", + "sandwich", + "burger", + "pizza", + "mouse", + "keyboard", +] + +let nextId = 1 + +function buildData(count) { + const data = new Array(count) + for (let i = 0; i < count; i++) { + data[i] = { + id: nextId++, + label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)] + }`, + } + } + return data +} + +function listReducer(state, action) { + const { data, selected } = state + switch (action.type) { + case "RUN": + return { data: buildData(1000), selected: 0 } + case "RUN_LOTS": + return { data: buildData(10000), selected: 0 } + case "ADD": + return { data: data.concat(buildData(1000)), selected } + case "UPDATE": + const newData = data.slice(0) + for (let i = 0; i < newData.length; i += 10) { + const r = newData[i] + newData[i] = { id: r.id, label: r.label + " !!!" } + } + return { data: newData, selected } + case "CLEAR": + return { data: [], selected: 0 } + case "SWAP_ROWS": + return data.length > 998 ? { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected } : state + case "REMOVE": + const idx = data.findIndex((d) => d.id === action.id) + return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected } + case "SELECT": + return { data, selected: action.id } + } + return state +} + +const Row = ({ selected, item, dispatch, id }) => { + return ( + + {item.id} + + dispatch({ type: 'SELECT', id: item.id }) + }>{item.label} + + + dispatch({ type: 'REMOVE', id: item.id })}> + + + + + ) +} + +const Button = ({ id, cb, title }) => ( +
+ +
+) + + +const Jumbotron = ({ dispatch }) => ( +
+
+
+

Fre Hooks keyed

+
+
+
+
+
+
+
+) + +const Main = () => { + const [state, setState] = useReducer(listReducer, { data: [], selected: 0 }) + const dispatch = useCallback(setState, []) + + return ( +
+ + + + {state.data.map((item) => { + return ( + + ) + })} + +
+ +
+ ) } -render(, document.body) \ No newline at end of file + +render(
, document.body) \ No newline at end of file diff --git a/demo/index.html b/index.html similarity index 81% rename from demo/index.html rename to index.html index 86c2cc7..8b3183e 100644 --- a/demo/index.html +++ b/index.html @@ -7,6 +7,6 @@ Document - + \ No newline at end of file diff --git a/src/index.js b/src/index.js index 9f834c5..4cd678c 100644 --- a/src/index.js +++ b/src/index.js @@ -151,7 +151,7 @@ function mount(vnode, isSvg) { setDOMAttribute(node, key, props[key], isSvg) } } - + let childrenRef = props.children == null ? null : mount(props.children, isSvg) childrenRef && insertDom(node, childrenRef) return { @@ -196,9 +196,11 @@ function reconcile( ref, isSvg ) { - if (oldVnode === newVnode && !newVnode.dirty) { - return ref - } else if (isEmpty(newVnode) && isEmpty(oldVnode)) { + // if (oldVnode === newVnode) { + // return ref + // } else + + if (isEmpty(newVnode) && isEmpty(oldVnode)) { return ref } else if (isLeaf(newVnode) && isLeaf(oldVnode)) { ref.node.nodeValue = newVnode @@ -208,10 +210,12 @@ function reconcile( isElement(oldVnode) && newVnode.type === oldVnode.type ) { + isSvg = isSvg || newVnode.type === 'svg' reconcileProps(ref.node, newVnode.props, oldVnode.props, isSvg) let oldCh = oldVnode.props.children let newCh = newVnode.props.children + if (oldCh == null) { if (newCh != null) { ref.children = mount(newCh, isSvg) @@ -232,19 +236,15 @@ function reconcile( } } return ref - } else if (isNonEmptyArray(newVnode) && isNonEmptyArray(oldVnode)) { - reconcileChildren(parent, newVnode, oldVnode, ref, isSvg) - return ref } else if ( isComponent(newVnode) && isComponent(oldVnode) && newVnode.type === oldVnode.type ) { - let fn = newVnode.type - let shouldUpdate = newVnode.dirty || (fn.shouldUpdate != null + let shouldUpdate = fn.shouldUpdate != null ? fn.shouldUpdate(oldVnode.props, newVnode.props) - : defaultShouldUpdate(oldVnode.props, newVnode.props)) + : defaultShouldUpdate(oldVnode.props, newVnode.props) if (shouldUpdate) { currentVnode = newVnode @@ -274,11 +274,9 @@ function reconcile( } else { return ref } - } else if (newVnode instanceof Node && oldVnode instanceof Node) { - ref.node = newVnode - return ref } else { - return mount(newVnode, isSvg) + reconcileChildren(parent, newVnode, oldVnode, ref, isSvg) + return ref } } @@ -435,8 +433,8 @@ const useReducer = ( : value if (hook[0] !== v) { hook[0] = v - c.dirty = true - defer(() => render(c, rootRef)) + c.type.shouldUpdate = () => true + render(c, rootRef) } } } diff --git a/demo/vite.config.js b/vite.config.js similarity index 100% rename from demo/vite.config.js rename to vite.config.js