@viewfly/core 3.0.0-alpha.0 → 3.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,7 +19,7 @@ pnpm add @viewfly/core
19
19
  import 'reflect-metadata'
20
20
  ```
21
21
 
22
- 更稳妥的做法以 [官网](https://viewfly.org) 与当前版本的说明为准。
22
+ 更稳妥的做法以**当前安装版本**随附的类型定义与 README 为准。
23
23
 
24
24
  ---
25
25
 
@@ -49,7 +49,7 @@ import 'reflect-metadata'
49
49
  | 组件 | 函数组件:在 JSX 中当标签使用;配合生命周期钩子使用。 |
50
50
  | 生命周期 | **`onMounted`**、**`onUpdated`**、**`onUnmounted`** 等(须在组件 setup 阶段调用)。 |
51
51
  | 响应式 | **`reactive`**、**`shallowReactive`**、**`watch`** 等(`reactive` 模块)。 |
52
- | 信号 | **`createSignal`**、**`createEffect`**、**`createDerived`** 等(`signals` 模块)。 |
52
+ | 信号 / 派生 | **`createSignal`**、**`computed`** 等(见 `reactive` 导出;具体符号以类型为准)。 |
53
53
  | 依赖注入 | 在组件内用 **`inject`** 解析 token;用 **`Injectable()`** 声明可注入类;用 **`withAnnotation`** 或 **`createContext`** / **`createContextProvider`** 挂载 **`Provider`**;根应用上通过 **`createApp(...).provide(...)`**(由 **`@viewfly/platform-browser`** 提供)注册全局提供者。 |
54
54
  | 自定义 DOM 属性标记 | **`withMark(marks, setup)`**:为组件渲染出的元素附加与 `marks` 同名的属性(常用于 scoped CSS 的 `scopeId` 等场景)。 |
55
55
 
@@ -59,7 +59,7 @@ import 'reflect-metadata'
59
59
 
60
60
  ## 文档与示例
61
61
 
62
- - **官方文档**:[viewfly.org](https://viewfly.org)
62
+ - **权威说明**:本文件、源码注释与发布包中的 **`.d.ts`**(第三方文档站点可能滞后)。
63
63
  - **本仓库试跑**:仓库根目录执行 `pnpm dev` 打开 playground
64
64
 
65
65
  ---
package/dist/index.esm.js CHANGED
@@ -1063,9 +1063,17 @@ function hasChange(newProps, oldProps) {
1063
1063
  return false;
1064
1064
  }
1065
1065
  function comparePropsWithCallbacks(oldProps, newProps, onDeleted, onAdded, onUpdated) {
1066
- for (const key in oldProps) if (!(key in newProps)) onDeleted(key, oldProps[key]);
1067
- for (const key in newProps) if (!(key in oldProps)) onAdded(key, newProps[key]);
1068
- else if (oldProps[key] !== newProps[key]) onUpdated(key, newProps[key], oldProps[key]);
1066
+ const oldKeys = Object.keys(oldProps);
1067
+ for (let i = 0; i < oldKeys.length; i++) {
1068
+ const key = oldKeys[i];
1069
+ if (!(key in newProps)) onDeleted(key, oldProps[key]);
1070
+ }
1071
+ const newKeys = Object.keys(newProps);
1072
+ for (let i = 0; i < newKeys.length; i++) {
1073
+ const key = newKeys[i];
1074
+ if (!(key in oldProps)) onAdded(key, newProps[key]);
1075
+ else if (oldProps[key] !== newProps[key]) onUpdated(key, newProps[key], oldProps[key]);
1076
+ }
1069
1077
  }
1070
1078
  function classToString(config) {
1071
1079
  if (typeof config === "string") return config;
@@ -1662,7 +1670,7 @@ var NativeRenderer = class {};
1662
1670
  //#endregion
1663
1671
  //#region src/base/renderer.ts
1664
1672
  var listenerReg = /^on[A-Z]/;
1665
- var nativeNodeRefRecord = /* @__PURE__ */ new Map();
1673
+ var nativeNodeRefRecord = /* @__PURE__ */ new WeakMap();
1666
1674
  function createRenderer(component, nativeRenderer, namespace) {
1667
1675
  let isInit = true;
1668
1676
  return function render(host) {
@@ -1729,24 +1737,85 @@ function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
1729
1737
  component.rendered();
1730
1738
  }
1731
1739
  }
1740
+ function createOldAtomMatcher(oldAtoms) {
1741
+ const typeMap = /* @__PURE__ */ new Map();
1742
+ const cursorMap = /* @__PURE__ */ new WeakMap();
1743
+ for (let i = 0; i < oldAtoms.length; i++) {
1744
+ const atom = oldAtoms[i];
1745
+ let nodeTypeMap = typeMap.get(atom.type);
1746
+ if (!nodeTypeMap) {
1747
+ nodeTypeMap = /* @__PURE__ */ new Map();
1748
+ typeMap.set(atom.type, nodeTypeMap);
1749
+ }
1750
+ let keyMap = nodeTypeMap.get(atom.nodeType);
1751
+ if (!keyMap) {
1752
+ keyMap = /* @__PURE__ */ new Map();
1753
+ nodeTypeMap.set(atom.nodeType, keyMap);
1754
+ }
1755
+ const key = atom.key;
1756
+ const indices = keyMap.get(key);
1757
+ if (indices) indices.push(i);
1758
+ else keyMap.set(key, [i]);
1759
+ }
1760
+ const take = (atom, matched) => {
1761
+ const nodeTypeMap = typeMap.get(atom.type);
1762
+ if (!nodeTypeMap) return -1;
1763
+ const keyMap = nodeTypeMap.get(atom.nodeType);
1764
+ if (!keyMap) return -1;
1765
+ const indices = keyMap.get(atom.key);
1766
+ if (!indices || !indices.length) return -1;
1767
+ let cursor = cursorMap.get(indices) ?? 0;
1768
+ while (cursor < indices.length) {
1769
+ const index = indices[cursor];
1770
+ cursor++;
1771
+ if (!matched[index]) {
1772
+ cursorMap.set(indices, cursor);
1773
+ return index;
1774
+ }
1775
+ }
1776
+ cursorMap.set(indices, cursor);
1777
+ return -1;
1778
+ };
1779
+ return { take };
1780
+ }
1732
1781
  function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMove) {
1733
1782
  const commits = [];
1734
- while (newAtom) {
1735
- oldAtom = createChanges(newAtom, oldAtom, commits);
1736
- newAtom = newAtom.sibling;
1737
- }
1783
+ const oldAtoms = [];
1738
1784
  let dirtyDiffAtom = oldAtom;
1739
1785
  while (dirtyDiffAtom) {
1740
- cleanView(nativeRenderer, dirtyDiffAtom, true);
1786
+ oldAtoms.push(dirtyDiffAtom);
1741
1787
  dirtyDiffAtom = dirtyDiffAtom.sibling;
1742
1788
  }
1789
+ const matched = new Array(oldAtoms.length).fill(false);
1790
+ const matcher = createOldAtomMatcher(oldAtoms);
1791
+ const pendingDeleteIndices = [];
1792
+ let cursor = newAtom;
1793
+ while (cursor) {
1794
+ const matchedIndex = matcher.take(cursor, matched);
1795
+ if (matchedIndex >= 0) {
1796
+ matched[matchedIndex] = true;
1797
+ commits.push({
1798
+ dirtyAtom: oldAtoms[matchedIndex],
1799
+ newAtom: cursor
1800
+ });
1801
+ } else commits.push({
1802
+ dirtyAtom: null,
1803
+ newAtom: cursor
1804
+ });
1805
+ cursor = cursor.sibling;
1806
+ }
1807
+ for (let i = 0; i < oldAtoms.length; i++) if (!matched[i]) {
1808
+ pendingDeleteIndices.push(i);
1809
+ cleanView(nativeRenderer, oldAtoms[i], true);
1810
+ }
1743
1811
  let offset = 0;
1812
+ let pendingDeleteCursor = 0;
1744
1813
  const len = commits.length;
1745
1814
  for (let i = 0; i < len; i++) {
1746
- while (oldAtom) {
1747
- if (oldAtom.index <= i) {
1815
+ while (pendingDeleteCursor < pendingDeleteIndices.length) {
1816
+ if (oldAtoms[pendingDeleteIndices[pendingDeleteCursor]].index <= i) {
1748
1817
  offset--;
1749
- oldAtom = oldAtom.sibling;
1818
+ pendingDeleteCursor++;
1750
1819
  continue;
1751
1820
  }
1752
1821
  break;
@@ -1769,29 +1838,6 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
1769
1838
  }
1770
1839
  }
1771
1840
  }
1772
- function createChanges(newAtom, oldAtom, commits) {
1773
- const startDiffAtom = oldAtom;
1774
- let prev = null;
1775
- while (oldAtom) {
1776
- if (oldAtom.type === newAtom.type && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
1777
- commits.push({
1778
- dirtyAtom: oldAtom,
1779
- newAtom
1780
- });
1781
- const next = oldAtom.sibling;
1782
- if (!prev) return next;
1783
- prev.sibling = next;
1784
- return startDiffAtom;
1785
- }
1786
- prev = oldAtom;
1787
- oldAtom = oldAtom.sibling;
1788
- }
1789
- commits.push({
1790
- dirtyAtom: null,
1791
- newAtom
1792
- });
1793
- return startDiffAtom;
1794
- }
1795
1841
  function updateText(nativeRenderer, context, offset, needMove, newAtom, oldAtom) {
1796
1842
  const nativeNode = oldAtom.nativeNode;
1797
1843
  newAtom.nativeNode = nativeNode;
@@ -1890,9 +1936,12 @@ function cleanView(nativeRenderer, atom, needClean) {
1890
1936
  }
1891
1937
  if (atom.type === ElementAtomType) {
1892
1938
  const record = nativeNodeRefRecord.get(atom);
1893
- if (record) record.forEach((fn) => {
1894
- if (typeof fn === "function") fn();
1895
- });
1939
+ if (record) {
1940
+ nativeNodeRefRecord.delete(atom);
1941
+ record.forEach((fn) => {
1942
+ if (typeof fn === "function") fn();
1943
+ });
1944
+ }
1896
1945
  }
1897
1946
  cleanChildren(atom, nativeRenderer, needClean);
1898
1947
  }
@@ -1981,7 +2030,10 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
1981
2030
  const nativeNode = nativeRenderer.createElement(jsxNode.type, namespace);
1982
2031
  const props = jsxNode.props;
1983
2032
  let bindingRefs;
1984
- for (const key in props) {
2033
+ const propKeys = Object.keys(props);
2034
+ const propKeyLen = propKeys.length;
2035
+ for (let i = 0; i < propKeyLen; i++) {
2036
+ const key = propKeys[i];
1985
2037
  if (key === "children") {
1986
2038
  atom.child = createElementChildren(jsxNode.type, props.children, nativeRenderer, namespace);
1987
2039
  continue;
@@ -2016,9 +2068,11 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
2016
2068
  });
2017
2069
  context.host = nativeNode;
2018
2070
  context.isParent = false;
2019
- const refEffects = /* @__PURE__ */ new Map();
2020
- nativeNodeRefRecord.set(atom, refEffects);
2021
- applyRefs(bindingRefs, nativeNode, refEffects);
2071
+ if (bindingRefs) {
2072
+ const refEffects = /* @__PURE__ */ new Map();
2073
+ nativeNodeRefRecord.set(atom, refEffects);
2074
+ applyRefs(bindingRefs, nativeNode, refEffects);
2075
+ }
2022
2076
  }
2023
2077
  function createTextNode(nativeRenderer, atom, context) {
2024
2078
  const nativeNode = nativeRenderer.createTextNode(atom.jsxNode, atom.namespace);
@@ -2037,8 +2091,20 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2037
2091
  reuseElementChildrenView(nativeRenderer, newAtom, context);
2038
2092
  return;
2039
2093
  }
2094
+ let unBindRefs;
2040
2095
  let bindRefs;
2041
2096
  let updatedChildren = false;
2097
+ const styleCache = /* @__PURE__ */ new WeakMap();
2098
+ const toStyleObject = (style) => {
2099
+ if (style && typeof style === "object") {
2100
+ const cached = styleCache.get(style);
2101
+ if (cached) return cached;
2102
+ const normalized = styleToObject(style);
2103
+ styleCache.set(style, normalized);
2104
+ return normalized;
2105
+ }
2106
+ return styleToObject(style);
2107
+ };
2042
2108
  comparePropsWithCallbacks(oldVNode.props, newVNode.props, (key, oldValue) => {
2043
2109
  if (key === "children") {
2044
2110
  updatedChildren = true;
@@ -2050,14 +2116,22 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2050
2116
  return;
2051
2117
  }
2052
2118
  if (key === "style") {
2053
- for (const styleName in styleToObject(oldValue)) nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
2119
+ const oldStyle = toStyleObject(oldValue);
2120
+ const styleNames = Object.keys(oldStyle);
2121
+ for (let i = 0; i < styleNames.length; i++) {
2122
+ const styleName = styleNames[i];
2123
+ nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
2124
+ }
2054
2125
  return;
2055
2126
  }
2056
2127
  if (listenerReg.test(key)) {
2057
2128
  if (typeof oldValue === "function") nativeRenderer.unListen(nativeNode, key, oldValue, isSvg);
2058
2129
  return;
2059
2130
  }
2060
- if (key === "ref") return;
2131
+ if (key === "ref") {
2132
+ unBindRefs = oldValue;
2133
+ return;
2134
+ }
2061
2135
  nativeRenderer.removeProperty(nativeNode, key, isSvg);
2062
2136
  }, (key, value) => {
2063
2137
  if (key === "children") {
@@ -2071,8 +2145,12 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2071
2145
  return;
2072
2146
  }
2073
2147
  if (key === "style") {
2074
- const styleObj = styleToObject(value);
2075
- for (const styleName in styleObj) nativeRenderer.setStyle(nativeNode, styleName, styleObj[styleName], isSvg);
2148
+ const styleObj = toStyleObject(value);
2149
+ const styleNames = Object.keys(styleObj);
2150
+ for (let i = 0; i < styleNames.length; i++) {
2151
+ const styleName = styleNames[i];
2152
+ nativeRenderer.setStyle(nativeNode, styleName, styleObj[styleName], isSvg);
2153
+ }
2076
2154
  return;
2077
2155
  }
2078
2156
  if (listenerReg.test(key)) {
@@ -2100,7 +2178,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2100
2178
  return;
2101
2179
  }
2102
2180
  if (key === "style") {
2103
- comparePropsWithCallbacks(styleToObject(oldValue), styleToObject(newValue), (styleName) => {
2181
+ comparePropsWithCallbacks(toStyleObject(oldValue), toStyleObject(newValue), (styleName) => {
2104
2182
  nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
2105
2183
  }, (styleName, styleValue) => {
2106
2184
  nativeRenderer.setStyle(nativeNode, styleName, styleValue, isSvg);
@@ -2115,17 +2193,26 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2115
2193
  return;
2116
2194
  }
2117
2195
  if (key === "ref") {
2196
+ unBindRefs = oldValue;
2118
2197
  bindRefs = newValue;
2119
2198
  return;
2120
2199
  }
2121
2200
  nativeRenderer.setProperty(nativeNode, key, newValue, isSvg);
2122
2201
  });
2123
2202
  if (!updatedChildren) newAtom.child = oldAtom.child;
2124
- let refEffects = nativeNodeRefRecord.get(oldAtom);
2125
- if (!refEffects) refEffects = /* @__PURE__ */ new Map();
2126
- nativeNodeRefRecord.delete(oldAtom);
2127
- nativeNodeRefRecord.set(newAtom, refEffects);
2128
- updateRefs(bindRefs, nativeNode, refEffects);
2203
+ if (bindRefs === unBindRefs) {
2204
+ const refEffects = nativeNodeRefRecord.get(oldAtom);
2205
+ if (refEffects) {
2206
+ nativeNodeRefRecord.delete(oldAtom);
2207
+ nativeNodeRefRecord.set(newAtom, refEffects);
2208
+ }
2209
+ } else {
2210
+ let refEffects = nativeNodeRefRecord.get(oldAtom);
2211
+ if (!refEffects) refEffects = /* @__PURE__ */ new Map();
2212
+ nativeNodeRefRecord.delete(oldAtom);
2213
+ nativeNodeRefRecord.set(newAtom, refEffects);
2214
+ updateRefs(bindRefs, nativeNode, refEffects);
2215
+ }
2129
2216
  }
2130
2217
  //#endregion
2131
2218
  //#region src/base/root.component.ts
@@ -2216,9 +2303,13 @@ function viewfly(config) {
2216
2303
  * @returns 一个对象,对象的 value 属性是计算的值
2217
2304
  */
2218
2305
  function computed(getter) {
2219
- return { get value() {
2220
- return getter();
2221
- } };
2306
+ const proxy = new Proxy({ value: null }, readonlyProxyHandler);
2307
+ watchEffect(() => {
2308
+ internalWrite(() => {
2309
+ proxy.value = getter();
2310
+ });
2311
+ });
2312
+ return proxy;
2222
2313
  }
2223
2314
  //#endregion
2224
2315
  //#region src/reactive/shallow-reactive.ts
package/dist/index.js CHANGED
@@ -1064,9 +1064,17 @@ function hasChange(newProps, oldProps) {
1064
1064
  return false;
1065
1065
  }
1066
1066
  function comparePropsWithCallbacks(oldProps, newProps, onDeleted, onAdded, onUpdated) {
1067
- for (const key in oldProps) if (!(key in newProps)) onDeleted(key, oldProps[key]);
1068
- for (const key in newProps) if (!(key in oldProps)) onAdded(key, newProps[key]);
1069
- else if (oldProps[key] !== newProps[key]) onUpdated(key, newProps[key], oldProps[key]);
1067
+ const oldKeys = Object.keys(oldProps);
1068
+ for (let i = 0; i < oldKeys.length; i++) {
1069
+ const key = oldKeys[i];
1070
+ if (!(key in newProps)) onDeleted(key, oldProps[key]);
1071
+ }
1072
+ const newKeys = Object.keys(newProps);
1073
+ for (let i = 0; i < newKeys.length; i++) {
1074
+ const key = newKeys[i];
1075
+ if (!(key in oldProps)) onAdded(key, newProps[key]);
1076
+ else if (oldProps[key] !== newProps[key]) onUpdated(key, newProps[key], oldProps[key]);
1077
+ }
1070
1078
  }
1071
1079
  function classToString(config) {
1072
1080
  if (typeof config === "string") return config;
@@ -2223,7 +2231,7 @@ var NativeRenderer = class {};
2223
2231
  //#endregion
2224
2232
  //#region src/base/renderer.ts
2225
2233
  var listenerReg = /^on[A-Z]/;
2226
- var nativeNodeRefRecord = /* @__PURE__ */ new Map();
2234
+ var nativeNodeRefRecord = /* @__PURE__ */ new WeakMap();
2227
2235
  function createRenderer(component, nativeRenderer, namespace) {
2228
2236
  let isInit = true;
2229
2237
  return function render(host) {
@@ -2290,24 +2298,85 @@ function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
2290
2298
  component.rendered();
2291
2299
  }
2292
2300
  }
2301
+ function createOldAtomMatcher(oldAtoms) {
2302
+ const typeMap = /* @__PURE__ */ new Map();
2303
+ const cursorMap = /* @__PURE__ */ new WeakMap();
2304
+ for (let i = 0; i < oldAtoms.length; i++) {
2305
+ const atom = oldAtoms[i];
2306
+ let nodeTypeMap = typeMap.get(atom.type);
2307
+ if (!nodeTypeMap) {
2308
+ nodeTypeMap = /* @__PURE__ */ new Map();
2309
+ typeMap.set(atom.type, nodeTypeMap);
2310
+ }
2311
+ let keyMap = nodeTypeMap.get(atom.nodeType);
2312
+ if (!keyMap) {
2313
+ keyMap = /* @__PURE__ */ new Map();
2314
+ nodeTypeMap.set(atom.nodeType, keyMap);
2315
+ }
2316
+ const key = atom.key;
2317
+ const indices = keyMap.get(key);
2318
+ if (indices) indices.push(i);
2319
+ else keyMap.set(key, [i]);
2320
+ }
2321
+ const take = (atom, matched) => {
2322
+ const nodeTypeMap = typeMap.get(atom.type);
2323
+ if (!nodeTypeMap) return -1;
2324
+ const keyMap = nodeTypeMap.get(atom.nodeType);
2325
+ if (!keyMap) return -1;
2326
+ const indices = keyMap.get(atom.key);
2327
+ if (!indices || !indices.length) return -1;
2328
+ let cursor = cursorMap.get(indices) ?? 0;
2329
+ while (cursor < indices.length) {
2330
+ const index = indices[cursor];
2331
+ cursor++;
2332
+ if (!matched[index]) {
2333
+ cursorMap.set(indices, cursor);
2334
+ return index;
2335
+ }
2336
+ }
2337
+ cursorMap.set(indices, cursor);
2338
+ return -1;
2339
+ };
2340
+ return { take };
2341
+ }
2293
2342
  function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMove) {
2294
2343
  const commits = [];
2295
- while (newAtom) {
2296
- oldAtom = createChanges(newAtom, oldAtom, commits);
2297
- newAtom = newAtom.sibling;
2298
- }
2344
+ const oldAtoms = [];
2299
2345
  let dirtyDiffAtom = oldAtom;
2300
2346
  while (dirtyDiffAtom) {
2301
- cleanView(nativeRenderer, dirtyDiffAtom, true);
2347
+ oldAtoms.push(dirtyDiffAtom);
2302
2348
  dirtyDiffAtom = dirtyDiffAtom.sibling;
2303
2349
  }
2350
+ const matched = new Array(oldAtoms.length).fill(false);
2351
+ const matcher = createOldAtomMatcher(oldAtoms);
2352
+ const pendingDeleteIndices = [];
2353
+ let cursor = newAtom;
2354
+ while (cursor) {
2355
+ const matchedIndex = matcher.take(cursor, matched);
2356
+ if (matchedIndex >= 0) {
2357
+ matched[matchedIndex] = true;
2358
+ commits.push({
2359
+ dirtyAtom: oldAtoms[matchedIndex],
2360
+ newAtom: cursor
2361
+ });
2362
+ } else commits.push({
2363
+ dirtyAtom: null,
2364
+ newAtom: cursor
2365
+ });
2366
+ cursor = cursor.sibling;
2367
+ }
2368
+ for (let i = 0; i < oldAtoms.length; i++) if (!matched[i]) {
2369
+ pendingDeleteIndices.push(i);
2370
+ cleanView(nativeRenderer, oldAtoms[i], true);
2371
+ }
2304
2372
  let offset = 0;
2373
+ let pendingDeleteCursor = 0;
2305
2374
  const len = commits.length;
2306
2375
  for (let i = 0; i < len; i++) {
2307
- while (oldAtom) {
2308
- if (oldAtom.index <= i) {
2376
+ while (pendingDeleteCursor < pendingDeleteIndices.length) {
2377
+ if (oldAtoms[pendingDeleteIndices[pendingDeleteCursor]].index <= i) {
2309
2378
  offset--;
2310
- oldAtom = oldAtom.sibling;
2379
+ pendingDeleteCursor++;
2311
2380
  continue;
2312
2381
  }
2313
2382
  break;
@@ -2330,29 +2399,6 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
2330
2399
  }
2331
2400
  }
2332
2401
  }
2333
- function createChanges(newAtom, oldAtom, commits) {
2334
- const startDiffAtom = oldAtom;
2335
- let prev = null;
2336
- while (oldAtom) {
2337
- if (oldAtom.type === newAtom.type && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
2338
- commits.push({
2339
- dirtyAtom: oldAtom,
2340
- newAtom
2341
- });
2342
- const next = oldAtom.sibling;
2343
- if (!prev) return next;
2344
- prev.sibling = next;
2345
- return startDiffAtom;
2346
- }
2347
- prev = oldAtom;
2348
- oldAtom = oldAtom.sibling;
2349
- }
2350
- commits.push({
2351
- dirtyAtom: null,
2352
- newAtom
2353
- });
2354
- return startDiffAtom;
2355
- }
2356
2402
  function updateText(nativeRenderer, context, offset, needMove, newAtom, oldAtom) {
2357
2403
  const nativeNode = oldAtom.nativeNode;
2358
2404
  newAtom.nativeNode = nativeNode;
@@ -2451,9 +2497,12 @@ function cleanView(nativeRenderer, atom, needClean) {
2451
2497
  }
2452
2498
  if (atom.type === ElementAtomType) {
2453
2499
  const record = nativeNodeRefRecord.get(atom);
2454
- if (record) record.forEach((fn) => {
2455
- if (typeof fn === "function") fn();
2456
- });
2500
+ if (record) {
2501
+ nativeNodeRefRecord.delete(atom);
2502
+ record.forEach((fn) => {
2503
+ if (typeof fn === "function") fn();
2504
+ });
2505
+ }
2457
2506
  }
2458
2507
  cleanChildren(atom, nativeRenderer, needClean);
2459
2508
  }
@@ -2542,7 +2591,10 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
2542
2591
  const nativeNode = nativeRenderer.createElement(jsxNode.type, namespace);
2543
2592
  const props = jsxNode.props;
2544
2593
  let bindingRefs;
2545
- for (const key in props) {
2594
+ const propKeys = Object.keys(props);
2595
+ const propKeyLen = propKeys.length;
2596
+ for (let i = 0; i < propKeyLen; i++) {
2597
+ const key = propKeys[i];
2546
2598
  if (key === "children") {
2547
2599
  atom.child = createElementChildren(jsxNode.type, props.children, nativeRenderer, namespace);
2548
2600
  continue;
@@ -2577,9 +2629,11 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
2577
2629
  });
2578
2630
  context.host = nativeNode;
2579
2631
  context.isParent = false;
2580
- const refEffects = /* @__PURE__ */ new Map();
2581
- nativeNodeRefRecord.set(atom, refEffects);
2582
- applyRefs(bindingRefs, nativeNode, refEffects);
2632
+ if (bindingRefs) {
2633
+ const refEffects = /* @__PURE__ */ new Map();
2634
+ nativeNodeRefRecord.set(atom, refEffects);
2635
+ applyRefs(bindingRefs, nativeNode, refEffects);
2636
+ }
2583
2637
  }
2584
2638
  function createTextNode(nativeRenderer, atom, context) {
2585
2639
  const nativeNode = nativeRenderer.createTextNode(atom.jsxNode, atom.namespace);
@@ -2598,8 +2652,20 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2598
2652
  reuseElementChildrenView(nativeRenderer, newAtom, context);
2599
2653
  return;
2600
2654
  }
2655
+ let unBindRefs;
2601
2656
  let bindRefs;
2602
2657
  let updatedChildren = false;
2658
+ const styleCache = /* @__PURE__ */ new WeakMap();
2659
+ const toStyleObject = (style) => {
2660
+ if (style && typeof style === "object") {
2661
+ const cached = styleCache.get(style);
2662
+ if (cached) return cached;
2663
+ const normalized = styleToObject(style);
2664
+ styleCache.set(style, normalized);
2665
+ return normalized;
2666
+ }
2667
+ return styleToObject(style);
2668
+ };
2603
2669
  comparePropsWithCallbacks(oldVNode.props, newVNode.props, (key, oldValue) => {
2604
2670
  if (key === "children") {
2605
2671
  updatedChildren = true;
@@ -2611,14 +2677,22 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2611
2677
  return;
2612
2678
  }
2613
2679
  if (key === "style") {
2614
- for (const styleName in styleToObject(oldValue)) nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
2680
+ const oldStyle = toStyleObject(oldValue);
2681
+ const styleNames = Object.keys(oldStyle);
2682
+ for (let i = 0; i < styleNames.length; i++) {
2683
+ const styleName = styleNames[i];
2684
+ nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
2685
+ }
2615
2686
  return;
2616
2687
  }
2617
2688
  if (listenerReg.test(key)) {
2618
2689
  if (typeof oldValue === "function") nativeRenderer.unListen(nativeNode, key, oldValue, isSvg);
2619
2690
  return;
2620
2691
  }
2621
- if (key === "ref") return;
2692
+ if (key === "ref") {
2693
+ unBindRefs = oldValue;
2694
+ return;
2695
+ }
2622
2696
  nativeRenderer.removeProperty(nativeNode, key, isSvg);
2623
2697
  }, (key, value) => {
2624
2698
  if (key === "children") {
@@ -2632,8 +2706,12 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2632
2706
  return;
2633
2707
  }
2634
2708
  if (key === "style") {
2635
- const styleObj = styleToObject(value);
2636
- for (const styleName in styleObj) nativeRenderer.setStyle(nativeNode, styleName, styleObj[styleName], isSvg);
2709
+ const styleObj = toStyleObject(value);
2710
+ const styleNames = Object.keys(styleObj);
2711
+ for (let i = 0; i < styleNames.length; i++) {
2712
+ const styleName = styleNames[i];
2713
+ nativeRenderer.setStyle(nativeNode, styleName, styleObj[styleName], isSvg);
2714
+ }
2637
2715
  return;
2638
2716
  }
2639
2717
  if (listenerReg.test(key)) {
@@ -2661,7 +2739,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2661
2739
  return;
2662
2740
  }
2663
2741
  if (key === "style") {
2664
- comparePropsWithCallbacks(styleToObject(oldValue), styleToObject(newValue), (styleName) => {
2742
+ comparePropsWithCallbacks(toStyleObject(oldValue), toStyleObject(newValue), (styleName) => {
2665
2743
  nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
2666
2744
  }, (styleName, styleValue) => {
2667
2745
  nativeRenderer.setStyle(nativeNode, styleName, styleValue, isSvg);
@@ -2676,17 +2754,26 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2676
2754
  return;
2677
2755
  }
2678
2756
  if (key === "ref") {
2757
+ unBindRefs = oldValue;
2679
2758
  bindRefs = newValue;
2680
2759
  return;
2681
2760
  }
2682
2761
  nativeRenderer.setProperty(nativeNode, key, newValue, isSvg);
2683
2762
  });
2684
2763
  if (!updatedChildren) newAtom.child = oldAtom.child;
2685
- let refEffects = nativeNodeRefRecord.get(oldAtom);
2686
- if (!refEffects) refEffects = /* @__PURE__ */ new Map();
2687
- nativeNodeRefRecord.delete(oldAtom);
2688
- nativeNodeRefRecord.set(newAtom, refEffects);
2689
- updateRefs(bindRefs, nativeNode, refEffects);
2764
+ if (bindRefs === unBindRefs) {
2765
+ const refEffects = nativeNodeRefRecord.get(oldAtom);
2766
+ if (refEffects) {
2767
+ nativeNodeRefRecord.delete(oldAtom);
2768
+ nativeNodeRefRecord.set(newAtom, refEffects);
2769
+ }
2770
+ } else {
2771
+ let refEffects = nativeNodeRefRecord.get(oldAtom);
2772
+ if (!refEffects) refEffects = /* @__PURE__ */ new Map();
2773
+ nativeNodeRefRecord.delete(oldAtom);
2774
+ nativeNodeRefRecord.set(newAtom, refEffects);
2775
+ updateRefs(bindRefs, nativeNode, refEffects);
2776
+ }
2690
2777
  }
2691
2778
  //#endregion
2692
2779
  //#region src/base/root.component.ts
@@ -2777,9 +2864,13 @@ function viewfly(config) {
2777
2864
  * @returns 一个对象,对象的 value 属性是计算的值
2778
2865
  */
2779
2866
  function computed(getter) {
2780
- return { get value() {
2781
- return getter();
2782
- } };
2867
+ const proxy = new Proxy({ value: null }, readonlyProxyHandler);
2868
+ watchEffect(() => {
2869
+ internalWrite(() => {
2870
+ proxy.value = getter();
2871
+ });
2872
+ });
2873
+ return proxy;
2783
2874
  }
2784
2875
  //#endregion
2785
2876
  //#region src/reactive/shallow-reactive.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viewfly/core",
3
- "version": "3.0.0-alpha.0",
3
+ "version": "3.0.0-alpha.2",
4
4
  "description": "Viewfly is a simple and easy-to-use JavaScript framework with an intuitive development experience.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.esm.js",