wevu 0.0.1 → 0.0.2-alpha.0

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/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as isReactive, c as touchReactive, d as stop, f as nextTick, i as isObject, l as computed, n as ref, o as reactive, p as queueJob, r as unref, s as toRaw, t as isRef, u as effect } from "./ref-DS-k2oUF.mjs";
1
+ import { _ as computed, a as isRef, b as nextTick, c as isObject, d as isShallowReactive, f as markRaw, g as touchReactive, h as toRaw, i as customRef, l as isRaw, m as shallowReactive, n as defineStore, o as ref, p as reactive, r as createStore, s as unref, t as storeToRefs, u as isReactive, v as effect, x as queueJob, y as stop } from "./store-BcU7YVhB.mjs";
2
2
 
3
3
  //#region src/reactivity/readonly.ts
4
4
  function readonly(target) {
@@ -30,6 +30,77 @@ function readonly(target) {
30
30
  });
31
31
  }
32
32
 
33
+ //#endregion
34
+ //#region src/reactivity/shallowRef.ts
35
+ function shallowRef(value, defaultValue) {
36
+ return customRef((track, trigger) => ({
37
+ get() {
38
+ track();
39
+ return value;
40
+ },
41
+ set(newValue) {
42
+ if (Object.is(value, newValue)) return;
43
+ value = newValue;
44
+ trigger();
45
+ }
46
+ }), defaultValue);
47
+ }
48
+ /**
49
+ * 判断传入值是否为浅层 ref。
50
+ *
51
+ * @param r 待判断的值
52
+ * @returns 若为浅层 ref 则返回 true
53
+ */
54
+ function isShallowRef(r) {
55
+ return r && typeof r === "object" && "value" in r && typeof r.value !== "function";
56
+ }
57
+ /**
58
+ * 主动触发一次浅层 ref 的更新(无需深度比较)。
59
+ *
60
+ * @param ref 需要触发的 ref
61
+ */
62
+ function triggerRef(ref$1) {
63
+ if (ref$1 && typeof ref$1 === "object" && "value" in ref$1) ref$1.value = ref$1.value;
64
+ }
65
+
66
+ //#endregion
67
+ //#region src/reactivity/toRefs.ts
68
+ /**
69
+ * 将一个响应式对象转换成“同结构的普通对象”,其中每个字段都是指向原对象对应属性的 ref。
70
+ *
71
+ * @param object 待转换的响应式对象
72
+ * @returns 包含若干 ref 的普通对象
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * const state = reactive({ foo: 1, bar: 2 })
77
+ * const stateAsRefs = toRefs(state)
78
+ *
79
+ * stateAsRefs.foo.value++ // 2
80
+ * state.foo // 2
81
+ * ```
82
+ */
83
+ function toRefs(object) {
84
+ if (!isReactive(object)) console.warn(`toRefs() expects a reactive object but received a plain one.`);
85
+ const result = Array.isArray(object) ? Array.from({ length: object.length }) : {};
86
+ for (const key in object) result[key] = toRef(object, key);
87
+ return result;
88
+ }
89
+ function toRef(object, key, defaultValue) {
90
+ const value = object[key];
91
+ if (isRef(value)) return value;
92
+ return customRef((track, trigger) => ({
93
+ get() {
94
+ track();
95
+ return object[key];
96
+ },
97
+ set(newValue) {
98
+ object[key] = newValue;
99
+ trigger();
100
+ }
101
+ }), defaultValue);
102
+ }
103
+
33
104
  //#endregion
34
105
  //#region src/reactivity/traverse.ts
35
106
  function traverse(value, seen = /* @__PURE__ */ new Set()) {
@@ -90,8 +161,8 @@ function watch(source, cb, options = {}) {
90
161
  };
91
162
  }
92
163
  /**
93
- * watchEffect registers a reactive effect with optional cleanup.
94
- * The effect executes immediately and re-runs when its dependencies change.
164
+ * watchEffect 注册一个响应式副作用,可选清理函数。
165
+ * 副作用会立即执行,并在依赖变化时重新运行。
95
166
  */
96
167
  function watchEffect(effectFn) {
97
168
  let cleanup;
@@ -397,9 +468,100 @@ function onAddToFavorites(handler) {
397
468
  if (!__currentInstance) throw new Error("onAddToFavorites() must be called synchronously inside setup()");
398
469
  pushHook(__currentInstance, "onAddToFavorites", handler, { single: true });
399
470
  }
471
+ /**
472
+ * Vue 3 对齐:组件/页面已挂载,映射小程序 onReady
473
+ */
474
+ function onMounted(handler) {
475
+ if (!__currentInstance) throw new Error("onMounted() must be called synchronously inside setup()");
476
+ pushHook(__currentInstance, "onReady", handler);
477
+ }
478
+ /**
479
+ * Vue 3 对齐:组件/页面更新后触发。
480
+ * 小程序没有专用 update 生命周期,这里在每次 setData 完成后调用。
481
+ */
482
+ function onUpdated(handler) {
483
+ if (!__currentInstance) throw new Error("onUpdated() must be called synchronously inside setup()");
484
+ pushHook(__currentInstance, "__wevuOnUpdated", handler);
485
+ }
486
+ /**
487
+ * Vue 3 对齐:卸载前触发。
488
+ * 小程序无 before-unload 生命周期,setup 时同步执行以保持语义。
489
+ */
490
+ function onBeforeUnmount(handler) {
491
+ if (!__currentInstance) throw new Error("onBeforeUnmount() must be called synchronously inside setup()");
492
+ handler();
493
+ }
494
+ /**
495
+ * Vue 3 对齐:组件/页面卸载;映射到页面 onUnload 或组件 detached
496
+ */
497
+ function onUnmounted(handler) {
498
+ if (!__currentInstance) throw new Error("onUnmounted() must be called synchronously inside setup()");
499
+ pushHook(__currentInstance, "onUnload", handler);
500
+ }
501
+ /**
502
+ * Vue 3 对齐:挂载前;setup 时同步触发以模拟 beforeMount 语义
503
+ */
504
+ function onBeforeMount(handler) {
505
+ if (!__currentInstance) throw new Error("onBeforeMount() must be called synchronously inside setup()");
506
+ handler();
507
+ }
508
+ /**
509
+ * Vue 3 对齐:更新前;在每次 setData 前触发
510
+ */
511
+ function onBeforeUpdate(handler) {
512
+ if (!__currentInstance) throw new Error("onBeforeUpdate() must be called synchronously inside setup()");
513
+ pushHook(__currentInstance, "__wevuOnBeforeUpdate", handler);
514
+ }
515
+ /**
516
+ * Vue 3 对齐:错误捕获;映射到小程序 onError
517
+ */
518
+ function onErrorCaptured(handler) {
519
+ if (!__currentInstance) throw new Error("onErrorCaptured() must be called synchronously inside setup()");
520
+ pushHook(__currentInstance, "onAppError", (err) => handler(err, __currentInstance, ""));
521
+ }
522
+ /**
523
+ * Vue 3 对齐:组件激活;映射到小程序 onShow
524
+ */
525
+ function onActivated(handler) {
526
+ if (!__currentInstance) throw new Error("onActivated() must be called synchronously inside setup()");
527
+ pushHook(__currentInstance, "onShow", handler);
528
+ }
529
+ /**
530
+ * Vue 3 对齐:组件失活;映射到小程序 onHide
531
+ */
532
+ function onDeactivated(handler) {
533
+ if (!__currentInstance) throw new Error("onDeactivated() must be called synchronously inside setup()");
534
+ pushHook(__currentInstance, "onHide", handler);
535
+ }
536
+ /**
537
+ * Vue 3 对齐:服务端渲染前置钩子。
538
+ * 小程序无此场景,保留空实现以保持 API 兼容。
539
+ */
540
+ function onServerPrefetch(_handler) {
541
+ if (!__currentInstance) throw new Error("onServerPrefetch() must be called synchronously inside setup()");
542
+ }
543
+ function callUpdateHooks(target, phase) {
544
+ callHookList(target, phase === "before" ? "__wevuOnBeforeUpdate" : "__wevuOnUpdated");
545
+ }
400
546
 
401
547
  //#endregion
402
548
  //#region src/runtime/register.ts
549
+ function runSetupFunction(setup, props, context) {
550
+ if (typeof setup !== "function") return;
551
+ const runtimeContext = context?.runtime ?? {
552
+ methods: Object.create(null),
553
+ state: {},
554
+ proxy: {},
555
+ watch: () => () => {},
556
+ bindModel: () => {}
557
+ };
558
+ if (context) context.runtime = runtimeContext;
559
+ const finalContext = {
560
+ ...context ?? {},
561
+ runtime: runtimeContext
562
+ };
563
+ return setup.length >= 2 ? setup(props, finalContext) : setup(finalContext);
564
+ }
403
565
  function normalizeWatchDescriptor(descriptor, runtime, instance) {
404
566
  if (typeof descriptor === "function") return {
405
567
  handler: descriptor.bind(runtime.proxy),
@@ -452,29 +614,54 @@ function mountRuntimeInstance(target, runtimeApp, watchMap, setup) {
452
614
  const runtime = runtimeApp.mount({ setData(payload) {
453
615
  if (typeof target.setData === "function") target.setData(payload);
454
616
  } });
617
+ const runtimeProxy = runtime?.proxy ?? {};
618
+ const runtimeState = runtime?.state ?? {};
619
+ if (!runtime?.methods) try {
620
+ runtime.methods = Object.create(null);
621
+ } catch {}
622
+ const runtimeMethods = runtime?.methods ?? Object.create(null);
623
+ const runtimeWatch = runtime?.watch ?? (() => () => {});
624
+ const runtimeBindModel = runtime?.bindModel ?? (() => {});
625
+ const runtimeWithDefaults = {
626
+ ...runtime ?? {},
627
+ state: runtimeState,
628
+ proxy: runtimeProxy,
629
+ methods: runtimeMethods,
630
+ watch: runtimeWatch,
631
+ bindModel: runtimeBindModel
632
+ };
455
633
  Object.defineProperty(target, "$wevu", {
456
- value: runtime,
634
+ value: runtimeWithDefaults,
457
635
  configurable: true,
458
636
  enumerable: false,
459
637
  writable: false
460
638
  });
461
- target.__wevu = runtime;
639
+ target.__wevu = runtimeWithDefaults;
462
640
  if (watchMap) {
463
- const stops = registerWatches(runtime, watchMap, target);
641
+ const stops = registerWatches(runtimeWithDefaults, watchMap, target);
464
642
  if (stops.length) target.__wevuWatchStops = stops;
465
643
  }
466
644
  if (setup) {
645
+ const props = target.properties || {};
467
646
  const context = {
468
- runtime,
469
- state: runtime.state,
470
- proxy: runtime.proxy,
471
- bindModel: runtime.bindModel.bind(runtime),
472
- watch: runtime.watch.bind(runtime),
473
- instance: target
647
+ props,
648
+ runtime: runtimeWithDefaults,
649
+ state: runtimeState,
650
+ proxy: runtimeProxy,
651
+ bindModel: runtimeBindModel.bind(runtimeWithDefaults),
652
+ watch: runtimeWatch.bind(runtimeWithDefaults),
653
+ instance: target,
654
+ emit: (event, ...args) => {
655
+ if (typeof target.triggerEvent === "function") target.triggerEvent(event, ...args);
656
+ },
657
+ expose: (exposed) => {
658
+ target.__wevuExposed = exposed;
659
+ },
660
+ attrs: {}
474
661
  };
475
662
  setCurrentInstance(target);
476
663
  try {
477
- const result = setup(context);
664
+ const result = runSetupFunction(setup, props, context);
478
665
  if (result && typeof result === "object") Object.keys(result).forEach((key) => {
479
666
  const val = result[key];
480
667
  if (typeof val === "function") runtime.methods[key] = (...args) => val.apply(runtime.proxy, args);
@@ -877,54 +1064,227 @@ function setComputedValue(setters, key, value) {
877
1064
 
878
1065
  //#endregion
879
1066
  //#region src/runtime/define.ts
1067
+ /**
1068
+ * 按 Vue 3 风格定义一个小程序组件(始终注册为 Component,页面请用 definePage)。
1069
+ *
1070
+ * @param options 组件定义项
1071
+ * @returns 可手动注册的组件定义
1072
+ *
1073
+ * @example
1074
+ * ```ts
1075
+ * defineComponent({
1076
+ * data: () => ({ count: 0 }),
1077
+ * setup() {
1078
+ * onMounted(() => console.log('mounted'))
1079
+ * }
1080
+ * })
1081
+ * ```
1082
+ */
880
1083
  function defineComponent(options) {
881
- const { type = "component", data, computed: computed$1, methods, watch: watch$1, setup, ...mpOptions } = options;
1084
+ const { data, computed: computed$1, methods, watch: watch$1, setup, props, ...mpOptions } = options;
1085
+ const mpOptionsWithProps = normalizeProps(mpOptions, props);
882
1086
  const runtimeApp = createApp({
883
1087
  data,
884
1088
  computed: computed$1,
885
1089
  methods
886
1090
  });
887
1091
  const setupWrapper = (ctx) => {
888
- const result = setup?.(ctx);
1092
+ const result = runSetupFunction(setup, ctx?.props ?? {}, ctx);
889
1093
  if (result) applySetupResult(ctx.runtime, ctx.instance, result);
890
1094
  };
891
- if (type === "component") registerComponent(runtimeApp, methods ?? {}, watch$1, setupWrapper, mpOptions);
892
- else registerPage(runtimeApp, methods ?? {}, watch$1, setupWrapper, mpOptions, void 0);
893
- return { mount: (_features) => {} };
1095
+ const componentOptions = {
1096
+ data,
1097
+ computed: computed$1,
1098
+ methods,
1099
+ watch: watch$1,
1100
+ setup: setupWrapper,
1101
+ mpOptions: mpOptionsWithProps
1102
+ };
1103
+ registerComponent(runtimeApp, methods ?? {}, watch$1, setupWrapper, mpOptionsWithProps);
1104
+ return {
1105
+ __wevu_runtime: runtimeApp,
1106
+ __wevu_options: componentOptions
1107
+ };
894
1108
  }
1109
+ /**
1110
+ * 按 Vue 3 风格定义一个小程序页面
1111
+ *
1112
+ * @param options 页面定义
1113
+ * @param features 页面特性(例如 listenPageScroll、enableShareAppMessage 等)
1114
+ * @returns 页面定义
1115
+ *
1116
+ * @example
1117
+ * ```ts
1118
+ * definePage({
1119
+ * data: () => ({ count: 0 }),
1120
+ * setup() {
1121
+ * const count = ref(0)
1122
+ * onMounted(() => console.log('page mounted'))
1123
+ * return { count }
1124
+ * }
1125
+ * }, {
1126
+ * listenPageScroll: true,
1127
+ * enableShareAppMessage: true
1128
+ * })
1129
+ * ```
1130
+ */
895
1131
  function definePage(options, features) {
896
- const { data, computed: computed$1, methods, watch: watch$1, setup, ...mpOptions } = options;
1132
+ const { data, computed: computed$1, methods, watch: watch$1, setup, props: _props, ...mpOptions } = options;
897
1133
  const runtimeApp = createApp({
898
1134
  data,
899
1135
  computed: computed$1,
900
1136
  methods
901
1137
  });
902
1138
  const setupWrapper = (ctx) => {
903
- const result = setup?.(ctx);
1139
+ const result = runSetupFunction(setup, ctx?.props ?? {}, ctx);
904
1140
  if (result) applySetupResult(ctx.runtime, ctx.instance, result);
905
1141
  };
1142
+ const componentOptions = {
1143
+ type: "page",
1144
+ data,
1145
+ computed: computed$1,
1146
+ methods,
1147
+ watch: watch$1,
1148
+ setup: setupWrapper,
1149
+ mpOptions,
1150
+ features
1151
+ };
906
1152
  registerPage(runtimeApp, methods ?? {}, watch$1, setupWrapper, mpOptions, features);
907
- return { mount: () => {} };
1153
+ return {
1154
+ mount: () => {},
1155
+ __wevu_runtime: runtimeApp,
1156
+ __wevu_options: componentOptions
1157
+ };
908
1158
  }
909
1159
  function applySetupResult(runtime, _target, result) {
1160
+ const methods = runtime?.methods ?? Object.create(null);
1161
+ const state = runtime?.state ?? Object.create(null);
1162
+ if (runtime && !runtime.methods) try {
1163
+ runtime.methods = methods;
1164
+ } catch {}
1165
+ if (runtime && !runtime.state) try {
1166
+ runtime.state = state;
1167
+ } catch {}
910
1168
  Object.keys(result).forEach((key) => {
911
1169
  const val = result[key];
912
- if (typeof val === "function") runtime.methods[key] = (...args) => val.apply(runtime.proxy, args);
913
- else runtime.state[key] = val;
1170
+ if (typeof val === "function") methods[key] = (...args) => val.apply(runtime?.proxy ?? runtime, args);
1171
+ else state[key] = val;
914
1172
  });
1173
+ if (runtime) {
1174
+ runtime.methods = runtime.methods ?? methods;
1175
+ runtime.state = runtime.state ?? state;
1176
+ }
1177
+ }
1178
+ /**
1179
+ * 从 Vue SFC 选项创建 wevu 组件,供 weapp-vite 编译产物直接调用的兼容入口。
1180
+ *
1181
+ * @param options 组件选项,可能包含小程序特有的 properties
1182
+ */
1183
+ function createWevuComponent(options) {
1184
+ const { properties, props, ...restOptions } = options;
1185
+ defineComponent(normalizeProps(restOptions, props, properties));
1186
+ }
1187
+ function normalizeProps(baseOptions, props, explicitProperties) {
1188
+ if (explicitProperties || !props) return {
1189
+ ...baseOptions,
1190
+ ...explicitProperties ? { properties: explicitProperties } : {}
1191
+ };
1192
+ const properties = {};
1193
+ Object.entries(props).forEach(([key, definition]) => {
1194
+ if (definition === null || definition === void 0) return;
1195
+ if (Array.isArray(definition) || typeof definition === "function") {
1196
+ properties[key] = { type: definition };
1197
+ return;
1198
+ }
1199
+ if (typeof definition === "object") {
1200
+ const propOptions = {};
1201
+ if ("type" in definition && definition.type !== void 0) propOptions.type = definition.type;
1202
+ const defaultValue = "default" in definition ? definition.default : definition.value;
1203
+ if (defaultValue !== void 0) propOptions.value = typeof defaultValue === "function" ? defaultValue() : defaultValue;
1204
+ properties[key] = propOptions;
1205
+ }
1206
+ });
1207
+ return {
1208
+ ...baseOptions,
1209
+ properties
1210
+ };
915
1211
  }
916
1212
 
917
1213
  //#endregion
918
1214
  //#region src/runtime/provide.ts
919
- const __wevuProvideStore = /* @__PURE__ */ new Map();
1215
+ const PROVIDE_SCOPE_KEY = Symbol("wevu.provideScope");
1216
+ const __wevuGlobalProvideStore = /* @__PURE__ */ new Map();
1217
+ /**
1218
+ * 在组件上下文中向后代注入值(与 Vue 3 行为兼容),若没有当前实例则回落到全局存储。
1219
+ *
1220
+ * @param key 注入键,可为字符串、Symbol 或对象
1221
+ * @param value 提供的值
1222
+ *
1223
+ * @example
1224
+ * ```ts
1225
+ * defineComponent({
1226
+ * setup() {
1227
+ * provide(TOKEN_KEY, { data: 'value' })
1228
+ * }
1229
+ * })
1230
+ * ```
1231
+ */
920
1232
  function provide(key, value) {
921
- __wevuProvideStore.set(key, value);
1233
+ const instance = getCurrentInstance();
1234
+ if (instance) {
1235
+ let scope = instance[PROVIDE_SCOPE_KEY];
1236
+ if (!scope) {
1237
+ scope = /* @__PURE__ */ new Map();
1238
+ instance[PROVIDE_SCOPE_KEY] = scope;
1239
+ }
1240
+ scope.set(key, value);
1241
+ } else __wevuGlobalProvideStore.set(key, value);
922
1242
  }
1243
+ /**
1244
+ * 从祖先组件(或全局存储)读取提供的值。
1245
+ *
1246
+ * @param key 注入键,需与 provide 使用的键保持一致
1247
+ * @param defaultValue 未找到提供者时的默认值
1248
+ * @returns 匹配到的值或默认值
1249
+ *
1250
+ * @example
1251
+ * ```ts
1252
+ * defineComponent({
1253
+ * setup() {
1254
+ * const data = inject(TOKEN_KEY)
1255
+ * const value = inject('key', 'default')
1256
+ * }
1257
+ * })
1258
+ * ```
1259
+ */
923
1260
  function inject(key, defaultValue) {
924
- if (__wevuProvideStore.has(key)) return __wevuProvideStore.get(key);
1261
+ const instance = getCurrentInstance();
1262
+ if (instance) {
1263
+ let current = instance;
1264
+ while (current) {
1265
+ const scope = current[PROVIDE_SCOPE_KEY];
1266
+ if (scope && scope.has(key)) return scope.get(key);
1267
+ current = null;
1268
+ }
1269
+ }
1270
+ if (__wevuGlobalProvideStore.has(key)) return __wevuGlobalProvideStore.get(key);
925
1271
  if (arguments.length >= 2) return defaultValue;
926
1272
  throw new Error(`wevu.inject: no value found for key`);
927
1273
  }
1274
+ /**
1275
+ * 全局注入值,适用于组件外部调用场景。
1276
+ */
1277
+ function provideGlobal(key, value) {
1278
+ __wevuGlobalProvideStore.set(key, value);
1279
+ }
1280
+ /**
1281
+ * 从全局存储读取值,适用于组件外部调用场景。
1282
+ */
1283
+ function injectGlobal(key, defaultValue) {
1284
+ if (__wevuGlobalProvideStore.has(key)) return __wevuGlobalProvideStore.get(key);
1285
+ if (arguments.length >= 2) return defaultValue;
1286
+ throw new Error(`injectGlobal() no matching provider for key: ${String(key)}`);
1287
+ }
928
1288
 
929
1289
  //#endregion
930
- export { callHookList, callHookReturn, computed, createApp, defineComponent, definePage, effect, getCurrentInstance, getDeepWatchStrategy, inject, isReactive, isRef, mountRuntimeInstance, nextTick, onAddToFavorites, onAppError, onAppHide, onAppShow, onHide, onPageScroll, onReady, onRouteDone, onSaveExitState, onShareAppMessage, onShareTimeline, onShow, onTabItemTap, onUnload, provide, reactive, readonly, ref, registerApp, registerComponent, registerPage, setCurrentInstance, setDeepWatchStrategy, stop, teardownRuntimeInstance, toRaw, touchReactive, traverse, unref, watch, watchEffect };
1290
+ export { callHookList, callHookReturn, callUpdateHooks, computed, createApp, createStore, createWevuComponent, defineComponent, definePage, defineStore, effect, getCurrentInstance, getDeepWatchStrategy, inject, injectGlobal, isRaw, isReactive, isRef, isShallowReactive, isShallowRef, markRaw, mountRuntimeInstance, nextTick, onActivated, onAddToFavorites, onAppError, onAppHide, onAppShow, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onErrorCaptured, onHide, onMounted, onPageScroll, onReady, onRouteDone, onSaveExitState, onServerPrefetch, onShareAppMessage, onShareTimeline, onShow, onTabItemTap, onUnload, onUnmounted, onUpdated, provide, provideGlobal, reactive, readonly, ref, registerApp, registerComponent, registerPage, runSetupFunction, setCurrentInstance, setDeepWatchStrategy, shallowReactive, shallowRef, stop, storeToRefs, teardownRuntimeInstance, toRaw, toRef, toRefs, touchReactive, traverse, triggerRef, unref, watch, watchEffect };