vue-page-store 0.4.1 → 0.5.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/README.md +174 -3
- package/dist/index.cjs.js +79 -19
- package/dist/index.d.ts +47 -2
- package/dist/index.esm.js +79 -20
- package/dist/index.umd.js +81 -23
- package/dist/index.umd.min.js +9 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
- **enter / leave** — 页面可见性生命周期
|
|
18
18
|
- **$setInterval** — 页面级定时器托管
|
|
19
19
|
- **event bus** — 页面内作用域通信
|
|
20
|
+
- **plugin** — 外部扩展机制(v0.5 新增)
|
|
20
21
|
|
|
21
22
|
页面离开时可以自动清理页面级定时器,页面销毁时 `$destroy` 一键回收,不污染全局。
|
|
22
23
|
|
|
@@ -176,6 +177,11 @@ export default {
|
|
|
176
177
|
| `init` | `function` | store 创建后一次性调用,`$vm` 已可用。适合拉字典、注册事件监听 |
|
|
177
178
|
| `enter` | `function` | 页面进入可见 / 可交互状态时触发 |
|
|
178
179
|
| `leave` | `function` | 页面离开可见 / 可交互状态时触发 |
|
|
180
|
+
| *其它字段* | *any* | 注册过的 plugin 可声明自己的字段(见 [Plugin](#plugin)) |
|
|
181
|
+
|
|
182
|
+
### `registerPlugin(plugin)` *(v0.5 新增)*
|
|
183
|
+
|
|
184
|
+
注册全局插件,详见 [Plugin](#plugin) 节。
|
|
179
185
|
|
|
180
186
|
### Store 实例属性与方法
|
|
181
187
|
|
|
@@ -260,24 +266,29 @@ v0.4.1 新增 `init`,用于 store 创建后的一次性初始化。
|
|
|
260
266
|
created() 开始
|
|
261
267
|
└→ useStore(this)
|
|
262
268
|
└→ createStoreInstance() ← state/source/getters/actions 就绪
|
|
269
|
+
└→ plugin.install() ← v0.5:plugin 安装($vm 尚未绑定)
|
|
263
270
|
└→ bindTo(this) ← $vm 赋值
|
|
264
271
|
└→ ★ init() ← $vm 可用,只执行一次
|
|
265
272
|
└→ created() 剩余代码
|
|
266
273
|
mounted()
|
|
267
274
|
└→ ★ enter() ← DOM 就绪,每次可见都执行
|
|
275
|
+
└→ plugin.enter() ← v0.5:plugin enter 钩子
|
|
268
276
|
|
|
269
277
|
--- keep-alive 切走 ---
|
|
270
278
|
deactivated()
|
|
271
279
|
└→ clearAllIntervals()
|
|
272
280
|
└→ ★ leave()
|
|
281
|
+
└→ plugin.leave() ← v0.5:plugin leave 钩子
|
|
273
282
|
|
|
274
283
|
--- keep-alive 切回 ---
|
|
275
284
|
activated()
|
|
276
285
|
└→ ★ enter() ← 重新开轮询、刷数据
|
|
286
|
+
└→ plugin.enter()
|
|
277
287
|
|
|
278
288
|
--- 页面销毁 ---
|
|
279
289
|
beforeDestroy()
|
|
280
290
|
└→ ★ leave()(如果还没 leave)
|
|
291
|
+
└→ plugin.destroy() ← v0.5:plugin destroy 钩子
|
|
281
292
|
└→ $destroy()
|
|
282
293
|
```
|
|
283
294
|
|
|
@@ -419,6 +430,128 @@ state: () => ({
|
|
|
419
430
|
})
|
|
420
431
|
```
|
|
421
432
|
|
|
433
|
+
## Plugin
|
|
434
|
+
|
|
435
|
+
*v0.5 新增。* Plugin 机制让外部库可以给 `definePageStore` options 增加**新字段**并消费它,同时挂钩 enter / leave / destroy 生命周期——而不需要修改 page-store 本身。
|
|
436
|
+
|
|
437
|
+
> 典型场景:`vue-page-runtime`(请求编排)、`vue-page-persist`(状态持久化)、devtools 扩展。
|
|
438
|
+
|
|
439
|
+
### 协议
|
|
440
|
+
|
|
441
|
+
Plugin 是一个对象,包含 `name` 和 `install`:
|
|
442
|
+
|
|
443
|
+
```js
|
|
444
|
+
{
|
|
445
|
+
name: 'tasks', // 同时作为 options 字段匹配键
|
|
446
|
+
install(store, fieldValue, { Vue }) { // fieldValue === options.tasks
|
|
447
|
+
// 初始化 plugin 自己的逻辑
|
|
448
|
+
return {
|
|
449
|
+
enter() { /* page enter 后调用 */ },
|
|
450
|
+
leave() { /* page leave 后调用 */ },
|
|
451
|
+
destroy() { /* store 销毁时调用 */ },
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
- **匹配规则**:`options[plugin.name] !== undefined` 才会调用 `install`。没有声明字段的 store 完全不受影响。
|
|
458
|
+
- **install 时机**:store 创建末尾,state / getters / actions / $source / $setInterval / $emit 等全部就绪。`$vm` 此时**尚未**绑定。
|
|
459
|
+
- **返回值**:可选 `{ enter?, leave?, destroy? }`。不需要钩子可以不返回。
|
|
460
|
+
|
|
461
|
+
### 注册
|
|
462
|
+
|
|
463
|
+
全局注册一次即可:
|
|
464
|
+
|
|
465
|
+
```js
|
|
466
|
+
// main.js
|
|
467
|
+
import { registerPlugin } from 'vue-page-store'
|
|
468
|
+
import taskPlugin from 'vue-page-runtime/plugin'
|
|
469
|
+
|
|
470
|
+
registerPlugin(taskPlugin)
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
之后正常写 store,声明插件字段:
|
|
474
|
+
|
|
475
|
+
```js
|
|
476
|
+
import { definePageStore } from 'vue-page-store' // 入口不变
|
|
477
|
+
|
|
478
|
+
definePageStore('order', {
|
|
479
|
+
state: () => ({ /* ... */ }),
|
|
480
|
+
|
|
481
|
+
// page-store 不认识这个字段,但会递给注册过的 plugin
|
|
482
|
+
tasks: {
|
|
483
|
+
fetchUser: {
|
|
484
|
+
trigger: 'enter',
|
|
485
|
+
async run() { return api.getUser(this.$vm.$route.params.id) },
|
|
486
|
+
},
|
|
487
|
+
fetchOrders: {
|
|
488
|
+
deps: ['fetchUser'],
|
|
489
|
+
async run() { /* ... */ },
|
|
490
|
+
},
|
|
491
|
+
},
|
|
492
|
+
})
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
### 写一个 plugin
|
|
496
|
+
|
|
497
|
+
最小示例——一个把 `persist` 字段声明持久化到 localStorage 的插件:
|
|
498
|
+
|
|
499
|
+
```js
|
|
500
|
+
const persistPlugin = {
|
|
501
|
+
name: 'persist',
|
|
502
|
+
|
|
503
|
+
install(store, fieldValue /* options.persist */, { Vue }) {
|
|
504
|
+
const { key, paths } = fieldValue
|
|
505
|
+
|
|
506
|
+
// 恢复
|
|
507
|
+
try {
|
|
508
|
+
const saved = JSON.parse(localStorage.getItem(key) || '{}')
|
|
509
|
+
store.$patch(saved)
|
|
510
|
+
} catch (e) {}
|
|
511
|
+
|
|
512
|
+
// 持久化 —— 监听指定字段
|
|
513
|
+
const stopWatchers = paths.map(p =>
|
|
514
|
+
store._vm.$watch(
|
|
515
|
+
() => store[p],
|
|
516
|
+
(val) => {
|
|
517
|
+
const cur = JSON.parse(localStorage.getItem(key) || '{}')
|
|
518
|
+
cur[p] = val
|
|
519
|
+
localStorage.setItem(key, JSON.stringify(cur))
|
|
520
|
+
}
|
|
521
|
+
)
|
|
522
|
+
)
|
|
523
|
+
|
|
524
|
+
return {
|
|
525
|
+
destroy() {
|
|
526
|
+
stopWatchers.forEach(stop => stop())
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
registerPlugin(persistPlugin)
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
使用:
|
|
536
|
+
|
|
537
|
+
```js
|
|
538
|
+
definePageStore('page', {
|
|
539
|
+
state: () => ({ keyword: '', filters: {} }),
|
|
540
|
+
persist: {
|
|
541
|
+
key: 'page:cache',
|
|
542
|
+
paths: ['keyword', 'filters']
|
|
543
|
+
}
|
|
544
|
+
})
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### 注意事项
|
|
548
|
+
|
|
549
|
+
- **全局注册,影响所有 store**。plugin 只在对应 store 声明了 `options[plugin.name]` 时才激活,但注册本身是全局的。
|
|
550
|
+
- **同名 plugin 只能注册一次**,重复注册会被跳过并打印 warning。
|
|
551
|
+
- **install 返回的钩子会被按注册顺序依次调用**(FIFO)。
|
|
552
|
+
- **plugin 之间不通信**。如果两个 plugin 有依赖关系,应该合并成一个。
|
|
553
|
+
- **$vm 在 install 时为 null**。如果 plugin 需要组件实例,应在 `enter` 钩子里访问(此时 `$vm` 已绑定)。
|
|
554
|
+
|
|
422
555
|
## 实例模型:Singleton
|
|
423
556
|
|
|
424
557
|
当前版本采用 **id → singleton** 模型:
|
|
@@ -471,17 +604,43 @@ actions: {
|
|
|
471
604
|
|
|
472
605
|
## 调试
|
|
473
606
|
|
|
474
|
-
`storeRegistry`
|
|
607
|
+
### `storeRegistry` —— 导出的 Map
|
|
608
|
+
|
|
609
|
+
`storeRegistry` 是导出的 Map,可以在代码里用于调试或自定义 devtools 集成:
|
|
475
610
|
|
|
476
611
|
```js
|
|
477
612
|
import { storeRegistry } from 'vue-page-store'
|
|
478
613
|
|
|
479
|
-
// 查看所有活跃 store
|
|
480
614
|
storeRegistry.forEach((store, id) => {
|
|
481
615
|
console.log(id, store.$status, store.$disposed)
|
|
482
616
|
})
|
|
483
617
|
```
|
|
484
618
|
|
|
619
|
+
### `window.__VUE_PAGE_STORE__` —— dev 自动挂载 *(v0.5 新增)*
|
|
620
|
+
|
|
621
|
+
开发环境下(`process.env.NODE_ENV !== 'production'`)会自动挂到 `window.__VUE_PAGE_STORE__`,方便控制台访问。生产环境和 SSR 环境不会挂。
|
|
622
|
+
|
|
623
|
+
控制台用法:
|
|
624
|
+
|
|
625
|
+
```js
|
|
626
|
+
__VUE_PAGE_STORE__ // { registry, stores }
|
|
627
|
+
__VUE_PAGE_STORE__.stores // { orderList: {…}, userProfile: {…} }
|
|
628
|
+
__VUE_PAGE_STORE__.stores.orderList // ← 有属性自动补全
|
|
629
|
+
__VUE_PAGE_STORE__.stores.orderList.$source
|
|
630
|
+
__VUE_PAGE_STORE__.stores.orderList.$loading
|
|
631
|
+
|
|
632
|
+
// 原始 Map 也保留
|
|
633
|
+
__VUE_PAGE_STORE__.registry.forEach(...)
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
- `registry`:导出的原始 Map,和 `import { storeRegistry }` 拿到的是同一个引用
|
|
637
|
+
- `stores`:getter,每次读取重建对象视图;销毁的 store 自动消失
|
|
638
|
+
|
|
639
|
+
**说明**:
|
|
640
|
+
|
|
641
|
+
- `__VUE_PAGE_STORE__` 是 dev-only 调试接口,shape 和键名可能在后续版本变化,**不要在生产代码里依赖**
|
|
642
|
+
- 微前端场景下,多个子应用都加载 vue-page-store 时,最后挂载的会覆盖前面的。如需共存,请退回手动挂载并用自己的命名
|
|
643
|
+
|
|
485
644
|
## 从 v0.3.x 升级
|
|
486
645
|
|
|
487
646
|
### Breaking Changes
|
|
@@ -536,11 +695,23 @@ v0.4.0 中:
|
|
|
536
695
|
- `$setInterval()`:页面级 interval 托管
|
|
537
696
|
- `$loading.xxx`:返回 Promise 的 action 自动追踪 loading
|
|
538
697
|
- `$vm`:只读逃生口,可在 init / enter 中访问 `$route / $router`
|
|
698
|
+
- `registerPlugin()`:外部扩展机制(v0.5)
|
|
699
|
+
|
|
700
|
+
## 从 v0.4.x 升级到 v0.5
|
|
701
|
+
|
|
702
|
+
v0.5 **完全向后兼容** v0.4.x:
|
|
703
|
+
|
|
704
|
+
- 所有 v0.4 的 API 行为不变
|
|
705
|
+
- 新增 `registerPlugin()` 导出,不注册 plugin 等同于 v0.4 行为
|
|
706
|
+
- options 现在允许包含插件声明的额外字段(如 `tasks`、`persist`)
|
|
707
|
+
- dev 环境自动挂 `window.__VUE_PAGE_STORE__`,方便控制台调试
|
|
708
|
+
|
|
709
|
+
升级只需要改版本号,无需改代码。
|
|
539
710
|
|
|
540
711
|
## Roadmap
|
|
541
712
|
|
|
542
713
|
- **Keyed instance** — `useStore(vm, scopeKey)` 支持同定义多实例
|
|
543
|
-
- **
|
|
714
|
+
- **Official plugins** — 随着 `vue-page-runtime` 等生态库成熟,补充第一方 plugin 文档
|
|
544
715
|
- **More page runtime helpers** — 在不增加心智负担的前提下继续补页面层能力
|
|
545
716
|
|
|
546
717
|
## License
|
package/dist/index.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* vue-page-store v0.
|
|
2
|
+
* vue-page-store v0.5.0
|
|
3
3
|
* (c) 2026 weijianjun
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
@@ -7,16 +7,18 @@
|
|
|
7
7
|
|
|
8
8
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
9
9
|
|
|
10
|
+
var Vue = require('vue');
|
|
11
|
+
|
|
10
12
|
/*!
|
|
11
|
-
* vue-page-store v0.
|
|
13
|
+
* vue-page-store v0.5.0
|
|
12
14
|
* (c) 2026 weijianjun
|
|
13
15
|
* @license MIT
|
|
14
16
|
*/
|
|
15
17
|
/**
|
|
16
|
-
* vue-page-store 0.
|
|
18
|
+
* vue-page-store 0.5.0 — Vue 2.6 Page Scope Runtime
|
|
17
19
|
*
|
|
18
20
|
* 页面级作用域运行时容器:
|
|
19
|
-
* source · state · getters · actions · watch · init/enter/leave · $setInterval · event bus
|
|
21
|
+
* source · state · getters · actions · watch · init/enter/leave · $setInterval · event bus · plugin
|
|
20
22
|
*
|
|
21
23
|
* v0.4 新增:
|
|
22
24
|
* source → 页面输入 / 原始返回,和业务 state 分开
|
|
@@ -27,12 +29,13 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
27
29
|
* v0.4.1 新增:
|
|
28
30
|
* init → store 创建后一次性初始化钩子,$vm 已可用
|
|
29
31
|
*
|
|
32
|
+
* v0.5 新增:
|
|
33
|
+
* plugin → registerPlugin 注册外部扩展,声明字段 + 生命周期钩子
|
|
34
|
+
*
|
|
30
35
|
* @author weijianjun
|
|
31
36
|
* @license MIT
|
|
32
37
|
*/
|
|
33
38
|
|
|
34
|
-
// Store 注册表(导出供调试 / devtools 使用)
|
|
35
|
-
var storeRegistry = new Map();
|
|
36
39
|
|
|
37
40
|
// ====== dev-only warning ======
|
|
38
41
|
var isDev = typeof process !== 'undefined'
|
|
@@ -45,6 +48,47 @@ function warn(msg) {
|
|
|
45
48
|
}
|
|
46
49
|
}
|
|
47
50
|
|
|
51
|
+
// Store 注册表(导出供调试 / devtools 使用)
|
|
52
|
+
var storeRegistry = new Map();
|
|
53
|
+
|
|
54
|
+
// v0.5 新增:dev 环境自动挂到 window,方便控制台调试
|
|
55
|
+
if (isDev && typeof window !== 'undefined') {
|
|
56
|
+
window.__VUE_PAGE_STORE__ = {
|
|
57
|
+
registry: storeRegistry,
|
|
58
|
+
get stores() {
|
|
59
|
+
var result = {};
|
|
60
|
+
storeRegistry.forEach(function (s, id) { result[id] = s; });
|
|
61
|
+
return result;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ====== v0.5 新增:plugin 机制 ======
|
|
67
|
+
var _plugins = [];
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 注册全局 plugin
|
|
71
|
+
*
|
|
72
|
+
* plugin.name 同时作为 options 字段匹配键:
|
|
73
|
+
* 当 definePageStore options 中存在 options[plugin.name] 时,
|
|
74
|
+
* page-store 会调用 plugin.install(store, fieldValue, { Vue })
|
|
75
|
+
*
|
|
76
|
+
* install 可返回 { enter, leave, destroy } 生命周期钩子
|
|
77
|
+
*/
|
|
78
|
+
function registerPlugin(plugin) {
|
|
79
|
+
if (!plugin || typeof plugin.name !== 'string') {
|
|
80
|
+
throw new Error('[vue-page-store] plugin 需要一个 name 属性');
|
|
81
|
+
}
|
|
82
|
+
if (typeof plugin.install !== 'function') {
|
|
83
|
+
throw new Error('[vue-page-store] plugin "' + plugin.name + '" 需要一个 install 方法');
|
|
84
|
+
}
|
|
85
|
+
if (_plugins.some(function (p) { return p.name === plugin.name; })) {
|
|
86
|
+
warn('plugin "' + plugin.name + '" 已注册,跳过重复注册');
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
_plugins.push(plugin);
|
|
90
|
+
}
|
|
91
|
+
|
|
48
92
|
function createStoreInstance(Vue, id, options) {
|
|
49
93
|
var initialState = options.state();
|
|
50
94
|
|
|
@@ -58,6 +102,9 @@ function createStoreInstance(Vue, id, options) {
|
|
|
58
102
|
var enterHook = typeof options.enter === 'function' ? options.enter : null;
|
|
59
103
|
var leaveHook = typeof options.leave === 'function' ? options.leave : null;
|
|
60
104
|
|
|
105
|
+
// ====== v0.5 新增:plugin hooks 闭包存储(由 install 填充) ======
|
|
106
|
+
var _pluginHooks = [];
|
|
107
|
+
|
|
61
108
|
// --- 用一个隐藏的 Vue 实例承载响应式 state + source + loading + computed getters ---
|
|
62
109
|
var computedDefs = {};
|
|
63
110
|
var store = { $disposed: false };
|
|
@@ -325,6 +372,8 @@ function createStoreInstance(Vue, id, options) {
|
|
|
325
372
|
enterHook.call(store);
|
|
326
373
|
}
|
|
327
374
|
store.$emit('page:enter');
|
|
375
|
+
// v0.5: plugin enter hooks
|
|
376
|
+
_pluginHooks.forEach(function (h) { if (h.enter) h.enter(); });
|
|
328
377
|
}
|
|
329
378
|
|
|
330
379
|
function runLeave() {
|
|
@@ -337,6 +386,8 @@ function createStoreInstance(Vue, id, options) {
|
|
|
337
386
|
leaveHook.call(store);
|
|
338
387
|
}
|
|
339
388
|
store.$emit('page:leave');
|
|
389
|
+
// v0.5: plugin leave hooks
|
|
390
|
+
_pluginHooks.forEach(function (h) { if (h.leave) h.leave(); });
|
|
340
391
|
}
|
|
341
392
|
|
|
342
393
|
// ====== bindTo 去重标记 ======
|
|
@@ -403,6 +454,7 @@ function createStoreInstance(Vue, id, options) {
|
|
|
403
454
|
* 销毁 store
|
|
404
455
|
*
|
|
405
456
|
* v0.4 变更:兜底清理 interval
|
|
457
|
+
* v0.5 变更:调用 plugin destroy 钩子
|
|
406
458
|
*/
|
|
407
459
|
store.$destroy = function () {
|
|
408
460
|
if (store.$disposed) return;
|
|
@@ -413,6 +465,9 @@ function createStoreInstance(Vue, id, options) {
|
|
|
413
465
|
// 兜底清理 interval(正常流程 leave 已经清过,这里防遗漏)
|
|
414
466
|
clearAllIntervals();
|
|
415
467
|
|
|
468
|
+
// v0.5: plugin destroy hooks
|
|
469
|
+
_pluginHooks.forEach(function (h) { if (h.destroy) h.destroy(); });
|
|
470
|
+
|
|
416
471
|
store.$disposed = true;
|
|
417
472
|
Object.keys(_listeners).forEach(function (key) { delete _listeners[key]; });
|
|
418
473
|
vm.$destroy();
|
|
@@ -421,6 +476,15 @@ function createStoreInstance(Vue, id, options) {
|
|
|
421
476
|
|
|
422
477
|
store._vm = vm;
|
|
423
478
|
|
|
479
|
+
// ====== v0.5 新增:plugin 安装 ======
|
|
480
|
+
// 放在最后,此时 store 的 state/getters/actions/$源数据/$setInterval 等全部就绪
|
|
481
|
+
_plugins.forEach(function (plugin) {
|
|
482
|
+
var fieldValue = options[plugin.name];
|
|
483
|
+
if (fieldValue === undefined) return;
|
|
484
|
+
var hooks = plugin.install(store, fieldValue, { Vue: Vue });
|
|
485
|
+
if (hooks) _pluginHooks.push(hooks);
|
|
486
|
+
});
|
|
487
|
+
|
|
424
488
|
return store;
|
|
425
489
|
}
|
|
426
490
|
|
|
@@ -433,6 +497,8 @@ function createStoreInstance(Vue, id, options) {
|
|
|
433
497
|
* - actions 中的 async 函数自动追踪 $loading
|
|
434
498
|
* v0.4.1 变更:
|
|
435
499
|
* - options 新增 init(bindTo 之后一次性调用)
|
|
500
|
+
* v0.5 变更:
|
|
501
|
+
* - options 中注册过的 plugin.name 字段会被交给对应 plugin 处理
|
|
436
502
|
*/
|
|
437
503
|
function definePageStore(id, options) {
|
|
438
504
|
// 入参校验
|
|
@@ -443,7 +509,7 @@ function definePageStore(id, options) {
|
|
|
443
509
|
throw new Error('[vue-page-store] definePageStore("' + id + '") 需要 state 为函数');
|
|
444
510
|
}
|
|
445
511
|
|
|
446
|
-
var _Vue =
|
|
512
|
+
var _Vue = Vue;
|
|
447
513
|
|
|
448
514
|
return function useStore(componentVm) {
|
|
449
515
|
if (storeRegistry.has(id)) {
|
|
@@ -452,17 +518,6 @@ function definePageStore(id, options) {
|
|
|
452
518
|
return existing;
|
|
453
519
|
}
|
|
454
520
|
|
|
455
|
-
if (!_Vue) {
|
|
456
|
-
try {
|
|
457
|
-
_Vue = require('vue');
|
|
458
|
-
if (_Vue.default) _Vue = _Vue.default;
|
|
459
|
-
} catch (e) {
|
|
460
|
-
throw new Error(
|
|
461
|
-
'[vue-page-store] 无法自动获取 Vue,请确保 vue 已安装'
|
|
462
|
-
);
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
|
|
466
521
|
var store = createStoreInstance(_Vue, id, options);
|
|
467
522
|
storeRegistry.set(id, store);
|
|
468
523
|
if (componentVm) store.bindTo(componentVm);
|
|
@@ -476,8 +531,13 @@ function definePageStore(id, options) {
|
|
|
476
531
|
};
|
|
477
532
|
}
|
|
478
533
|
|
|
479
|
-
var index = {
|
|
534
|
+
var index = {
|
|
535
|
+
definePageStore: definePageStore,
|
|
536
|
+
registerPlugin: registerPlugin,
|
|
537
|
+
storeRegistry: storeRegistry
|
|
538
|
+
};
|
|
480
539
|
|
|
481
540
|
exports.default = index;
|
|
482
541
|
exports.definePageStore = definePageStore;
|
|
542
|
+
exports.registerPlugin = registerPlugin;
|
|
483
543
|
exports.storeRegistry = storeRegistry;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* vue-page-store v0.
|
|
2
|
+
* vue-page-store v0.5.0 - TypeScript 类型定义
|
|
3
3
|
*
|
|
4
4
|
* Page Scope Runtime for Vue 2.6
|
|
5
5
|
*/
|
|
@@ -68,6 +68,9 @@ export interface StoreOptions<
|
|
|
68
68
|
* interval 在 leave 前已自动清理
|
|
69
69
|
*/
|
|
70
70
|
leave?: (this: PageStore<S, Src>) => void;
|
|
71
|
+
|
|
72
|
+
/** 允许 plugin 声明的额外字段(v0.5 新增) */
|
|
73
|
+
[key: string]: any;
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
export interface Store<
|
|
@@ -138,6 +141,8 @@ export type PageStore<
|
|
|
138
141
|
* - async action 自动追踪 $loading
|
|
139
142
|
* v0.4.1 变更:
|
|
140
143
|
* - options 新增 init(bindTo 之后一次性调用)
|
|
144
|
+
* v0.5 变更:
|
|
145
|
+
* - options 支持 plugin 声明的自定义字段
|
|
141
146
|
*/
|
|
142
147
|
export declare function definePageStore<
|
|
143
148
|
S extends Record<string, any>,
|
|
@@ -148,4 +153,44 @@ export declare function definePageStore<
|
|
|
148
153
|
): (componentVm?: Vue2ComponentInstance) => PageStore<S, Src>;
|
|
149
154
|
|
|
150
155
|
/** Store 注册表 */
|
|
151
|
-
export declare const storeRegistry: Map<string, PageStore<any, any>>;
|
|
156
|
+
export declare const storeRegistry: Map<string, PageStore<any, any>>;
|
|
157
|
+
|
|
158
|
+
// ====== v0.5 新增:plugin 类型 ======
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Plugin install 返回的生命周期钩子(v0.5 新增)
|
|
162
|
+
* page-store 会在对应时机调用
|
|
163
|
+
*/
|
|
164
|
+
export interface PluginHooks {
|
|
165
|
+
/** 每次 page enter 之后调用(用户 enter hook + page:enter event 之后) */
|
|
166
|
+
enter?: () => void;
|
|
167
|
+
/** 每次 page leave 之后调用(用户 leave hook + page:leave event 之后) */
|
|
168
|
+
leave?: () => void;
|
|
169
|
+
/** store $destroy 时调用,用于释放 plugin 自己的资源 */
|
|
170
|
+
destroy?: () => void;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Plugin 定义(v0.5 新增)
|
|
175
|
+
*
|
|
176
|
+
* plugin.name 同时作为字段名:
|
|
177
|
+
* 当 definePageStore options 中存在 options[name] 时,
|
|
178
|
+
* page-store 会调用 install(store, fieldValue, { Vue })
|
|
179
|
+
*
|
|
180
|
+
* install 在 store 创建末尾、bindTo 之前执行,此时 state/getters/actions/$source/$setInterval 已就绪
|
|
181
|
+
*/
|
|
182
|
+
export interface PageStorePlugin {
|
|
183
|
+
name: string;
|
|
184
|
+
install(
|
|
185
|
+
store: PageStore<any, any>,
|
|
186
|
+
fieldValue: any,
|
|
187
|
+
context: { Vue: any }
|
|
188
|
+
): PluginHooks | void;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* 注册全局 plugin(v0.5 新增)
|
|
193
|
+
*
|
|
194
|
+
* 同名 plugin 重复注册会被跳过并打印 warning
|
|
195
|
+
*/
|
|
196
|
+
export declare function registerPlugin(plugin: PageStorePlugin): void;
|
package/dist/index.esm.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* vue-page-store v0.
|
|
2
|
+
* vue-page-store v0.5.0
|
|
3
3
|
* (c) 2026 weijianjun
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
6
|
+
import Vue from 'vue';
|
|
7
|
+
|
|
6
8
|
/*!
|
|
7
|
-
* vue-page-store v0.
|
|
9
|
+
* vue-page-store v0.5.0
|
|
8
10
|
* (c) 2026 weijianjun
|
|
9
11
|
* @license MIT
|
|
10
12
|
*/
|
|
11
13
|
/**
|
|
12
|
-
* vue-page-store 0.
|
|
14
|
+
* vue-page-store 0.5.0 — Vue 2.6 Page Scope Runtime
|
|
13
15
|
*
|
|
14
16
|
* 页面级作用域运行时容器:
|
|
15
|
-
* source · state · getters · actions · watch · init/enter/leave · $setInterval · event bus
|
|
17
|
+
* source · state · getters · actions · watch · init/enter/leave · $setInterval · event bus · plugin
|
|
16
18
|
*
|
|
17
19
|
* v0.4 新增:
|
|
18
20
|
* source → 页面输入 / 原始返回,和业务 state 分开
|
|
@@ -23,12 +25,13 @@
|
|
|
23
25
|
* v0.4.1 新增:
|
|
24
26
|
* init → store 创建后一次性初始化钩子,$vm 已可用
|
|
25
27
|
*
|
|
28
|
+
* v0.5 新增:
|
|
29
|
+
* plugin → registerPlugin 注册外部扩展,声明字段 + 生命周期钩子
|
|
30
|
+
*
|
|
26
31
|
* @author weijianjun
|
|
27
32
|
* @license MIT
|
|
28
33
|
*/
|
|
29
34
|
|
|
30
|
-
// Store 注册表(导出供调试 / devtools 使用)
|
|
31
|
-
var storeRegistry = new Map();
|
|
32
35
|
|
|
33
36
|
// ====== dev-only warning ======
|
|
34
37
|
var isDev = typeof process !== 'undefined'
|
|
@@ -41,6 +44,47 @@ function warn(msg) {
|
|
|
41
44
|
}
|
|
42
45
|
}
|
|
43
46
|
|
|
47
|
+
// Store 注册表(导出供调试 / devtools 使用)
|
|
48
|
+
var storeRegistry = new Map();
|
|
49
|
+
|
|
50
|
+
// v0.5 新增:dev 环境自动挂到 window,方便控制台调试
|
|
51
|
+
if (isDev && typeof window !== 'undefined') {
|
|
52
|
+
window.__VUE_PAGE_STORE__ = {
|
|
53
|
+
registry: storeRegistry,
|
|
54
|
+
get stores() {
|
|
55
|
+
var result = {};
|
|
56
|
+
storeRegistry.forEach(function (s, id) { result[id] = s; });
|
|
57
|
+
return result;
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ====== v0.5 新增:plugin 机制 ======
|
|
63
|
+
var _plugins = [];
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 注册全局 plugin
|
|
67
|
+
*
|
|
68
|
+
* plugin.name 同时作为 options 字段匹配键:
|
|
69
|
+
* 当 definePageStore options 中存在 options[plugin.name] 时,
|
|
70
|
+
* page-store 会调用 plugin.install(store, fieldValue, { Vue })
|
|
71
|
+
*
|
|
72
|
+
* install 可返回 { enter, leave, destroy } 生命周期钩子
|
|
73
|
+
*/
|
|
74
|
+
function registerPlugin(plugin) {
|
|
75
|
+
if (!plugin || typeof plugin.name !== 'string') {
|
|
76
|
+
throw new Error('[vue-page-store] plugin 需要一个 name 属性');
|
|
77
|
+
}
|
|
78
|
+
if (typeof plugin.install !== 'function') {
|
|
79
|
+
throw new Error('[vue-page-store] plugin "' + plugin.name + '" 需要一个 install 方法');
|
|
80
|
+
}
|
|
81
|
+
if (_plugins.some(function (p) { return p.name === plugin.name; })) {
|
|
82
|
+
warn('plugin "' + plugin.name + '" 已注册,跳过重复注册');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
_plugins.push(plugin);
|
|
86
|
+
}
|
|
87
|
+
|
|
44
88
|
function createStoreInstance(Vue, id, options) {
|
|
45
89
|
var initialState = options.state();
|
|
46
90
|
|
|
@@ -54,6 +98,9 @@ function createStoreInstance(Vue, id, options) {
|
|
|
54
98
|
var enterHook = typeof options.enter === 'function' ? options.enter : null;
|
|
55
99
|
var leaveHook = typeof options.leave === 'function' ? options.leave : null;
|
|
56
100
|
|
|
101
|
+
// ====== v0.5 新增:plugin hooks 闭包存储(由 install 填充) ======
|
|
102
|
+
var _pluginHooks = [];
|
|
103
|
+
|
|
57
104
|
// --- 用一个隐藏的 Vue 实例承载响应式 state + source + loading + computed getters ---
|
|
58
105
|
var computedDefs = {};
|
|
59
106
|
var store = { $disposed: false };
|
|
@@ -321,6 +368,8 @@ function createStoreInstance(Vue, id, options) {
|
|
|
321
368
|
enterHook.call(store);
|
|
322
369
|
}
|
|
323
370
|
store.$emit('page:enter');
|
|
371
|
+
// v0.5: plugin enter hooks
|
|
372
|
+
_pluginHooks.forEach(function (h) { if (h.enter) h.enter(); });
|
|
324
373
|
}
|
|
325
374
|
|
|
326
375
|
function runLeave() {
|
|
@@ -333,6 +382,8 @@ function createStoreInstance(Vue, id, options) {
|
|
|
333
382
|
leaveHook.call(store);
|
|
334
383
|
}
|
|
335
384
|
store.$emit('page:leave');
|
|
385
|
+
// v0.5: plugin leave hooks
|
|
386
|
+
_pluginHooks.forEach(function (h) { if (h.leave) h.leave(); });
|
|
336
387
|
}
|
|
337
388
|
|
|
338
389
|
// ====== bindTo 去重标记 ======
|
|
@@ -399,6 +450,7 @@ function createStoreInstance(Vue, id, options) {
|
|
|
399
450
|
* 销毁 store
|
|
400
451
|
*
|
|
401
452
|
* v0.4 变更:兜底清理 interval
|
|
453
|
+
* v0.5 变更:调用 plugin destroy 钩子
|
|
402
454
|
*/
|
|
403
455
|
store.$destroy = function () {
|
|
404
456
|
if (store.$disposed) return;
|
|
@@ -409,6 +461,9 @@ function createStoreInstance(Vue, id, options) {
|
|
|
409
461
|
// 兜底清理 interval(正常流程 leave 已经清过,这里防遗漏)
|
|
410
462
|
clearAllIntervals();
|
|
411
463
|
|
|
464
|
+
// v0.5: plugin destroy hooks
|
|
465
|
+
_pluginHooks.forEach(function (h) { if (h.destroy) h.destroy(); });
|
|
466
|
+
|
|
412
467
|
store.$disposed = true;
|
|
413
468
|
Object.keys(_listeners).forEach(function (key) { delete _listeners[key]; });
|
|
414
469
|
vm.$destroy();
|
|
@@ -417,6 +472,15 @@ function createStoreInstance(Vue, id, options) {
|
|
|
417
472
|
|
|
418
473
|
store._vm = vm;
|
|
419
474
|
|
|
475
|
+
// ====== v0.5 新增:plugin 安装 ======
|
|
476
|
+
// 放在最后,此时 store 的 state/getters/actions/$源数据/$setInterval 等全部就绪
|
|
477
|
+
_plugins.forEach(function (plugin) {
|
|
478
|
+
var fieldValue = options[plugin.name];
|
|
479
|
+
if (fieldValue === undefined) return;
|
|
480
|
+
var hooks = plugin.install(store, fieldValue, { Vue: Vue });
|
|
481
|
+
if (hooks) _pluginHooks.push(hooks);
|
|
482
|
+
});
|
|
483
|
+
|
|
420
484
|
return store;
|
|
421
485
|
}
|
|
422
486
|
|
|
@@ -429,6 +493,8 @@ function createStoreInstance(Vue, id, options) {
|
|
|
429
493
|
* - actions 中的 async 函数自动追踪 $loading
|
|
430
494
|
* v0.4.1 变更:
|
|
431
495
|
* - options 新增 init(bindTo 之后一次性调用)
|
|
496
|
+
* v0.5 变更:
|
|
497
|
+
* - options 中注册过的 plugin.name 字段会被交给对应 plugin 处理
|
|
432
498
|
*/
|
|
433
499
|
function definePageStore(id, options) {
|
|
434
500
|
// 入参校验
|
|
@@ -439,7 +505,7 @@ function definePageStore(id, options) {
|
|
|
439
505
|
throw new Error('[vue-page-store] definePageStore("' + id + '") 需要 state 为函数');
|
|
440
506
|
}
|
|
441
507
|
|
|
442
|
-
var _Vue =
|
|
508
|
+
var _Vue = Vue;
|
|
443
509
|
|
|
444
510
|
return function useStore(componentVm) {
|
|
445
511
|
if (storeRegistry.has(id)) {
|
|
@@ -448,17 +514,6 @@ function definePageStore(id, options) {
|
|
|
448
514
|
return existing;
|
|
449
515
|
}
|
|
450
516
|
|
|
451
|
-
if (!_Vue) {
|
|
452
|
-
try {
|
|
453
|
-
_Vue = require('vue');
|
|
454
|
-
if (_Vue.default) _Vue = _Vue.default;
|
|
455
|
-
} catch (e) {
|
|
456
|
-
throw new Error(
|
|
457
|
-
'[vue-page-store] 无法自动获取 Vue,请确保 vue 已安装'
|
|
458
|
-
);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
|
|
462
517
|
var store = createStoreInstance(_Vue, id, options);
|
|
463
518
|
storeRegistry.set(id, store);
|
|
464
519
|
if (componentVm) store.bindTo(componentVm);
|
|
@@ -472,6 +527,10 @@ function definePageStore(id, options) {
|
|
|
472
527
|
};
|
|
473
528
|
}
|
|
474
529
|
|
|
475
|
-
var index = {
|
|
530
|
+
var index = {
|
|
531
|
+
definePageStore: definePageStore,
|
|
532
|
+
registerPlugin: registerPlugin,
|
|
533
|
+
storeRegistry: storeRegistry
|
|
534
|
+
};
|
|
476
535
|
|
|
477
|
-
export { index as default, definePageStore, storeRegistry };
|
|
536
|
+
export { index as default, definePageStore, registerPlugin, storeRegistry };
|
package/dist/index.umd.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* vue-page-store v0.
|
|
2
|
+
* vue-page-store v0.5.0
|
|
3
3
|
* (c) 2026 weijianjun
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
6
6
|
(function (global, factory) {
|
|
7
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
8
|
-
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
9
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.VuePageStore = {}));
|
|
10
|
-
})(this, (function (exports) { 'use strict';
|
|
7
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue')) :
|
|
8
|
+
typeof define === 'function' && define.amd ? define(['exports', 'vue'], factory) :
|
|
9
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.VuePageStore = {}, global.Vue));
|
|
10
|
+
})(this, (function (exports, Vue) { 'use strict';
|
|
11
11
|
|
|
12
12
|
/*!
|
|
13
|
-
* vue-page-store v0.
|
|
13
|
+
* vue-page-store v0.5.0
|
|
14
14
|
* (c) 2026 weijianjun
|
|
15
15
|
* @license MIT
|
|
16
16
|
*/
|
|
17
17
|
/**
|
|
18
|
-
* vue-page-store 0.
|
|
18
|
+
* vue-page-store 0.5.0 — Vue 2.6 Page Scope Runtime
|
|
19
19
|
*
|
|
20
20
|
* 页面级作用域运行时容器:
|
|
21
|
-
* source · state · getters · actions · watch · init/enter/leave · $setInterval · event bus
|
|
21
|
+
* source · state · getters · actions · watch · init/enter/leave · $setInterval · event bus · plugin
|
|
22
22
|
*
|
|
23
23
|
* v0.4 新增:
|
|
24
24
|
* source → 页面输入 / 原始返回,和业务 state 分开
|
|
@@ -29,12 +29,13 @@
|
|
|
29
29
|
* v0.4.1 新增:
|
|
30
30
|
* init → store 创建后一次性初始化钩子,$vm 已可用
|
|
31
31
|
*
|
|
32
|
+
* v0.5 新增:
|
|
33
|
+
* plugin → registerPlugin 注册外部扩展,声明字段 + 生命周期钩子
|
|
34
|
+
*
|
|
32
35
|
* @author weijianjun
|
|
33
36
|
* @license MIT
|
|
34
37
|
*/
|
|
35
38
|
|
|
36
|
-
// Store 注册表(导出供调试 / devtools 使用)
|
|
37
|
-
var storeRegistry = new Map();
|
|
38
39
|
|
|
39
40
|
// ====== dev-only warning ======
|
|
40
41
|
var isDev = typeof process !== 'undefined'
|
|
@@ -47,6 +48,47 @@
|
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
|
|
51
|
+
// Store 注册表(导出供调试 / devtools 使用)
|
|
52
|
+
var storeRegistry = new Map();
|
|
53
|
+
|
|
54
|
+
// v0.5 新增:dev 环境自动挂到 window,方便控制台调试
|
|
55
|
+
if (isDev && typeof window !== 'undefined') {
|
|
56
|
+
window.__VUE_PAGE_STORE__ = {
|
|
57
|
+
registry: storeRegistry,
|
|
58
|
+
get stores() {
|
|
59
|
+
var result = {};
|
|
60
|
+
storeRegistry.forEach(function (s, id) { result[id] = s; });
|
|
61
|
+
return result;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ====== v0.5 新增:plugin 机制 ======
|
|
67
|
+
var _plugins = [];
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 注册全局 plugin
|
|
71
|
+
*
|
|
72
|
+
* plugin.name 同时作为 options 字段匹配键:
|
|
73
|
+
* 当 definePageStore options 中存在 options[plugin.name] 时,
|
|
74
|
+
* page-store 会调用 plugin.install(store, fieldValue, { Vue })
|
|
75
|
+
*
|
|
76
|
+
* install 可返回 { enter, leave, destroy } 生命周期钩子
|
|
77
|
+
*/
|
|
78
|
+
function registerPlugin(plugin) {
|
|
79
|
+
if (!plugin || typeof plugin.name !== 'string') {
|
|
80
|
+
throw new Error('[vue-page-store] plugin 需要一个 name 属性');
|
|
81
|
+
}
|
|
82
|
+
if (typeof plugin.install !== 'function') {
|
|
83
|
+
throw new Error('[vue-page-store] plugin "' + plugin.name + '" 需要一个 install 方法');
|
|
84
|
+
}
|
|
85
|
+
if (_plugins.some(function (p) { return p.name === plugin.name; })) {
|
|
86
|
+
warn('plugin "' + plugin.name + '" 已注册,跳过重复注册');
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
_plugins.push(plugin);
|
|
90
|
+
}
|
|
91
|
+
|
|
50
92
|
function createStoreInstance(Vue, id, options) {
|
|
51
93
|
var initialState = options.state();
|
|
52
94
|
|
|
@@ -60,6 +102,9 @@
|
|
|
60
102
|
var enterHook = typeof options.enter === 'function' ? options.enter : null;
|
|
61
103
|
var leaveHook = typeof options.leave === 'function' ? options.leave : null;
|
|
62
104
|
|
|
105
|
+
// ====== v0.5 新增:plugin hooks 闭包存储(由 install 填充) ======
|
|
106
|
+
var _pluginHooks = [];
|
|
107
|
+
|
|
63
108
|
// --- 用一个隐藏的 Vue 实例承载响应式 state + source + loading + computed getters ---
|
|
64
109
|
var computedDefs = {};
|
|
65
110
|
var store = { $disposed: false };
|
|
@@ -327,6 +372,8 @@
|
|
|
327
372
|
enterHook.call(store);
|
|
328
373
|
}
|
|
329
374
|
store.$emit('page:enter');
|
|
375
|
+
// v0.5: plugin enter hooks
|
|
376
|
+
_pluginHooks.forEach(function (h) { if (h.enter) h.enter(); });
|
|
330
377
|
}
|
|
331
378
|
|
|
332
379
|
function runLeave() {
|
|
@@ -339,6 +386,8 @@
|
|
|
339
386
|
leaveHook.call(store);
|
|
340
387
|
}
|
|
341
388
|
store.$emit('page:leave');
|
|
389
|
+
// v0.5: plugin leave hooks
|
|
390
|
+
_pluginHooks.forEach(function (h) { if (h.leave) h.leave(); });
|
|
342
391
|
}
|
|
343
392
|
|
|
344
393
|
// ====== bindTo 去重标记 ======
|
|
@@ -405,6 +454,7 @@
|
|
|
405
454
|
* 销毁 store
|
|
406
455
|
*
|
|
407
456
|
* v0.4 变更:兜底清理 interval
|
|
457
|
+
* v0.5 变更:调用 plugin destroy 钩子
|
|
408
458
|
*/
|
|
409
459
|
store.$destroy = function () {
|
|
410
460
|
if (store.$disposed) return;
|
|
@@ -415,6 +465,9 @@
|
|
|
415
465
|
// 兜底清理 interval(正常流程 leave 已经清过,这里防遗漏)
|
|
416
466
|
clearAllIntervals();
|
|
417
467
|
|
|
468
|
+
// v0.5: plugin destroy hooks
|
|
469
|
+
_pluginHooks.forEach(function (h) { if (h.destroy) h.destroy(); });
|
|
470
|
+
|
|
418
471
|
store.$disposed = true;
|
|
419
472
|
Object.keys(_listeners).forEach(function (key) { delete _listeners[key]; });
|
|
420
473
|
vm.$destroy();
|
|
@@ -423,6 +476,15 @@
|
|
|
423
476
|
|
|
424
477
|
store._vm = vm;
|
|
425
478
|
|
|
479
|
+
// ====== v0.5 新增:plugin 安装 ======
|
|
480
|
+
// 放在最后,此时 store 的 state/getters/actions/$源数据/$setInterval 等全部就绪
|
|
481
|
+
_plugins.forEach(function (plugin) {
|
|
482
|
+
var fieldValue = options[plugin.name];
|
|
483
|
+
if (fieldValue === undefined) return;
|
|
484
|
+
var hooks = plugin.install(store, fieldValue, { Vue: Vue });
|
|
485
|
+
if (hooks) _pluginHooks.push(hooks);
|
|
486
|
+
});
|
|
487
|
+
|
|
426
488
|
return store;
|
|
427
489
|
}
|
|
428
490
|
|
|
@@ -435,6 +497,8 @@
|
|
|
435
497
|
* - actions 中的 async 函数自动追踪 $loading
|
|
436
498
|
* v0.4.1 变更:
|
|
437
499
|
* - options 新增 init(bindTo 之后一次性调用)
|
|
500
|
+
* v0.5 变更:
|
|
501
|
+
* - options 中注册过的 plugin.name 字段会被交给对应 plugin 处理
|
|
438
502
|
*/
|
|
439
503
|
function definePageStore(id, options) {
|
|
440
504
|
// 入参校验
|
|
@@ -445,7 +509,7 @@
|
|
|
445
509
|
throw new Error('[vue-page-store] definePageStore("' + id + '") 需要 state 为函数');
|
|
446
510
|
}
|
|
447
511
|
|
|
448
|
-
var _Vue =
|
|
512
|
+
var _Vue = Vue;
|
|
449
513
|
|
|
450
514
|
return function useStore(componentVm) {
|
|
451
515
|
if (storeRegistry.has(id)) {
|
|
@@ -454,17 +518,6 @@
|
|
|
454
518
|
return existing;
|
|
455
519
|
}
|
|
456
520
|
|
|
457
|
-
if (!_Vue) {
|
|
458
|
-
try {
|
|
459
|
-
_Vue = require('vue');
|
|
460
|
-
if (_Vue.default) _Vue = _Vue.default;
|
|
461
|
-
} catch (e) {
|
|
462
|
-
throw new Error(
|
|
463
|
-
'[vue-page-store] 无法自动获取 Vue,请确保 vue 已安装'
|
|
464
|
-
);
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
|
|
468
521
|
var store = createStoreInstance(_Vue, id, options);
|
|
469
522
|
storeRegistry.set(id, store);
|
|
470
523
|
if (componentVm) store.bindTo(componentVm);
|
|
@@ -478,10 +531,15 @@
|
|
|
478
531
|
};
|
|
479
532
|
}
|
|
480
533
|
|
|
481
|
-
var index = {
|
|
534
|
+
var index = {
|
|
535
|
+
definePageStore: definePageStore,
|
|
536
|
+
registerPlugin: registerPlugin,
|
|
537
|
+
storeRegistry: storeRegistry
|
|
538
|
+
};
|
|
482
539
|
|
|
483
540
|
exports.default = index;
|
|
484
541
|
exports.definePageStore = definePageStore;
|
|
542
|
+
exports.registerPlugin = registerPlugin;
|
|
485
543
|
exports.storeRegistry = storeRegistry;
|
|
486
544
|
|
|
487
545
|
Object.defineProperty(exports, '__esModule', { value: true });
|
package/dist/index.umd.min.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* vue-page-store v0.
|
|
2
|
+
* vue-page-store v0.5.0
|
|
3
3
|
* (c) 2026 weijianjun
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
6
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).VuePageStore={})}(this,function(e){"use strict";
|
|
6
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vue")):"function"==typeof define&&define.amd?define(["exports","vue"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).VuePageStore={},e.Vue)}(this,function(e,t){"use strict";
|
|
7
7
|
/*!
|
|
8
|
-
* vue-page-store v0.
|
|
8
|
+
* vue-page-store v0.5.0
|
|
9
9
|
* (c) 2026 weijianjun
|
|
10
10
|
* @license MIT
|
|
11
11
|
*/
|
|
12
12
|
/**
|
|
13
|
-
* vue-page-store 0.
|
|
13
|
+
* vue-page-store 0.5.0 — Vue 2.6 Page Scope Runtime
|
|
14
14
|
*
|
|
15
15
|
* 页面级作用域运行时容器:
|
|
16
|
-
* source · state · getters · actions · watch · init/enter/leave · $setInterval · event bus
|
|
16
|
+
* source · state · getters · actions · watch · init/enter/leave · $setInterval · event bus · plugin
|
|
17
17
|
*
|
|
18
18
|
* v0.4 新增:
|
|
19
19
|
* source → 页面输入 / 原始返回,和业务 state 分开
|
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
* v0.4.1 新增:
|
|
25
25
|
* init → store 创建后一次性初始化钩子,$vm 已可用
|
|
26
26
|
*
|
|
27
|
+
* v0.5 新增:
|
|
28
|
+
* plugin → registerPlugin 注册外部扩展,声明字段 + 生命周期钩子
|
|
29
|
+
*
|
|
27
30
|
* @author weijianjun
|
|
28
31
|
* @license MIT
|
|
29
|
-
*/var
|
|
32
|
+
*/var n="undefined"!=typeof process&&process.env&&"production"!==process.env.NODE_ENV;function o(e){n&&console.warn("[vue-page-store] "+e)}var r=new Map;n&&"undefined"!=typeof window&&(window.__VUE_PAGE_STORE__={registry:r,get stores(){var e={};return r.forEach(function(t,n){e[n]=t}),e}});var i=[];function u(e){if(!e||"string"!=typeof e.name)throw new Error("[vue-page-store] plugin 需要一个 name 属性");if("function"!=typeof e.install)throw new Error('[vue-page-store] plugin "'+e.name+'" 需要一个 install 方法');i.some(function(t){return t.name===e.name})?o('plugin "'+e.name+'" 已注册,跳过重复注册'):i.push(e)}function a(e,t,n){var u=n.state(),a="function"==typeof n.source?n.source():{},f=n.getters||{},c=n.actions||{},s="function"==typeof n.enter?n.enter:null,d="function"==typeof n.leave?n.leave:null,l=[],p={},v={$disposed:!1};Object.keys(f).forEach(function(e){p[e]=function(){return f[e].call(v)}});var $=new e({data:function(){return{$$state:u,$$source:a,$$loading:{},$$status:{mounted:!1,active:!1}}},computed:p}),h=$.$data.$$state,y=$.$data.$$source,g=$.$data.$$loading,b=$.$data.$$status;Object.keys(u).forEach(function(e){Object.defineProperty(v,e,{enumerable:!0,configurable:!0,get:function(){return h[e]},set:function(n){v.$disposed?o('store "'+t+'" 已销毁,忽略对 "'+e+'" 的写入'):h[e]=n}})}),v.$source=y,v.$loading=g,Object.keys(f).forEach(function(e){Object.defineProperty(v,e,{enumerable:!0,get:function(){return $[e]}})});var m={};function E(t){m[t]--,m[t]<=0&&(m[t]=0,e.set(g,t,!1))}Object.keys(c).forEach(function(t){var n=c[t].bind(v);v[t]=function(){var o=n.apply(null,arguments);o&&"function"==typeof o.then&&(m[t]||(m[t]=0),m[t]++,e.set(g,t,!0),Promise.resolve(o).then(function(){E(t)},function(){E(t)}));return o}});var O=n.watch||{};Object.entries(O).forEach(function(e){var n,r,i=e[0],u=e[1];if("function"==typeof u)n=u,r={};else if(n=u.handler,r={},u.deep&&(r.deep=!0),u.immediate&&(r.immediate=!0),!n)return void o('watch "'+i+'" in store "'+t+'" 缺少 handler,该 watcher 将被跳过');$.$watch(function(){return i.split(".").reduce(function(e,t){return e&&e[t]},v)},n.bind(v),r)}),v.$state=h,v.$status=b,v.$id=t;var w=null;Object.defineProperty(v,"$vm",{enumerable:!0,configurable:!1,get:function(){return w},set:function(){o("$vm 是只读属性,不允许业务侧重写")}}),v.$patch=function(n){if(v.$disposed)o('store "'+t+'" 已销毁,忽略 $patch 操作');else{var r="function"==typeof n?n(h):n;Object.keys(r).forEach(function(t){e.set(h,t,r[t])})}},v.$reset=function(){var t=n.state();Object.keys(t).forEach(function(n){e.set(h,n,t[n])}),Object.keys(h).forEach(function(n){n in t||e.delete(h,n)});var o="function"==typeof n.source?n.source():{};Object.keys(o).forEach(function(t){e.set(y,t,o[t])}),Object.keys(y).forEach(function(t){t in o||e.delete(y,t)})};var j={};v.$emit=function(e,t){var n=j[e];n&&n.slice().forEach(function(e){e(t)})},v.$on=function(e,t){return j[e]||(j[e]=[]),j[e].push(t),function(){if(j[e]){var n=j[e].indexOf(t);n>-1&&j[e].splice(n,1)}}},v.$off=function(e,t){if(j[e])if(t){var n=j[e].indexOf(t);n>-1&&j[e].splice(n,1)}else delete j[e]};var k=[];function P(){k.forEach(function(e){e.stopped||(clearInterval(e.id),e.stopped=!0)}),k.length=0}v.$setInterval=function(e,t){var n={id:setInterval(e,t),stopped:!1};k.push(n);return function(){if(!n.stopped){clearInterval(n.id),n.stopped=!0;var e=k.indexOf(n);e>-1&&k.splice(e,1)}}};var _=!1;function S(){_||(_=!0,b.mounted=!0,b.active=!0,s&&s.call(v),v.$emit("page:enter"),l.forEach(function(e){e.enter&&e.enter()}))}function x(){_&&(P(),_=!1,b.active=!1,d&&d.call(v),v.$emit("page:leave"),l.forEach(function(e){e.leave&&e.leave()}))}var T="undefined"!=typeof WeakSet?new WeakSet:null,V=T?null:[];return v.bindTo=function(e){return v.$disposed||function(e){return T?T.has(e):V.indexOf(e)>-1}(e)||(function(e){T?T.add(e):V.push(e)}(e),w=e,(e._provided||(e._provided={})).pageStore=v,e.$on("hook:mounted",function(){S()}),e.$on("hook:activated",function(){S()}),e.$on("hook:deactivated",function(){x()}),e.$on("hook:beforeDestroy",function(){x(),v.$destroy()})),v},v.$destroy=function(){v.$disposed||(b.mounted=!1,b.active=!1,P(),l.forEach(function(e){e.destroy&&e.destroy()}),v.$disposed=!0,Object.keys(j).forEach(function(e){delete j[e]}),$.$destroy(),r.delete(t))},v._vm=$,i.forEach(function(t){var o=n[t.name];if(void 0!==o){var r=t.install(v,o,{Vue:e});r&&l.push(r)}}),v}function f(e,n){if(!e||"string"!=typeof e)throw new Error("[vue-page-store] definePageStore 需要一个非空字符串作为 id");if(!n||"function"!=typeof n.state)throw new Error('[vue-page-store] definePageStore("'+e+'") 需要 state 为函数');var o=t;return function(t){if(r.has(e)){var i=r.get(e);return t&&i.bindTo(t),i}var u=a(o,e,n);return r.set(e,u),t&&u.bindTo(t),"function"==typeof n.init&&n.init.call(u),u}}var c={definePageStore:f,registerPlugin:u,storeRegistry:r};e.default=c,e.definePageStore=f,e.registerPlugin=u,e.storeRegistry=r,Object.defineProperty(e,"__esModule",{value:!0})});
|