vue-page-store 0.2.1 → 0.2.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
@@ -1,292 +1,292 @@
1
- # vue-page-store
2
-
3
- > Vue 2.6 页面级 Store —— 状态、通信、生命周期,一个作用域全收。
4
-
5
- ## 为什么需要它?
6
-
7
- 在微前端架构(single-spa / qiankun)下,复杂页面(仪表盘、漏斗分析、数据详情)的状态管理面临一个尴尬处境:
8
-
9
- | 方案 | 问题 |
10
- |------|------|
11
- | **Vuex** | 全局 store,页面销毁后状态残留,命名冲突,不适合页面级生命周期 |
12
- | **全局 EventBus** | 命名冲突、手动 $off 容易遗漏、事件扩散到全局 |
13
- | **provide / inject** | 只传数据,不管通信和副作用 |
14
- | **组件 data** | 跨组件共享困难,深层传递 props 地狱 |
15
-
16
- `vue-page-store` 解决的就是这个中间地带:**页面内部需要共享状态 + 通信 + 生命周期管理,但不应该污染全局。**
17
-
18
- ## 核心特性
19
-
20
- - **页面级作用域隔离** — 每个 store 独立一份 state 和事件,互不干扰
21
- - **`useStore(this)` 一行绑定** — 自动挂载生命周期,自动销毁,零手动清理
22
- - **页面生命周期** — `mount` / `unmount` / `activate` / `deactivate`,keep-alive 原生支持
23
- - **API 对齐 Pinia** — `state` / `getters` / `actions` / `$patch` / `$reset`,零学习成本
24
- - **内置作用域事件** — `$emit` / `$on` / `$off` 限定在当前 store 内,替代全局 EventBus
25
- - **声明式 watch** — 页面级副作用自动绑定生命周期
26
-
27
- ## 安装
28
-
29
- ```bash
30
- npm install vue-page-store
31
- ```
32
-
33
- > **前置条件**:项目中已安装 `vue@^2.6.0`
34
-
35
- ## 快速上手
36
-
37
- ### 1. 定义 Store
38
-
39
- ```javascript
40
- import { definePageStore } from 'vue-page-store';
41
-
42
- export const useFunnelStore = definePageStore('funnelDetail', {
43
- state: () => ({
44
- filters: { dateRange: [], platform: '' },
45
- loading: false,
46
- funnelSteps: [],
47
- }),
48
-
49
- getters: {
50
- isReady() {
51
- return !this.loading && this.funnelSteps.length > 0;
52
- },
53
- },
54
-
55
- actions: {
56
- async fetchData() {
57
- this.loading = true;
58
- try {
59
- this.funnelSteps = await api.getFunnelSteps(this.filters);
60
- } finally {
61
- this.loading = false;
62
- }
63
- },
64
- },
65
-
66
- watch: {
67
- 'filters.platform'(newVal) {
68
- this.fetchData();
69
- },
70
- },
71
-
72
- // 0.2.0 新增:页面生命周期
73
- lifecycle: {
74
- mount() {
75
- // 页面挂载时自动拉数据
76
- this.fetchData();
77
- },
78
- unmount() {
79
- console.log('页面销毁');
80
- },
81
- },
82
- });
83
- ```
84
-
85
- ### 2. 组件中使用
86
-
87
- ```javascript
88
- export default {
89
- created() {
90
- // 传 this → 自动绑定生命周期 + 自动销毁,不需要 beforeDestroy
91
- this.store = useFunnelStore(this);
92
- },
93
-
94
- computed: {
95
- isReady() {
96
- return this.store.isReady;
97
- },
98
- },
99
-
100
- methods: {
101
- handleSearch() {
102
- this.store.$patch({ filters: this.localFilters });
103
- this.store.fetchData();
104
- },
105
- },
106
- };
107
- ```
108
-
109
- > **不传 `this`** 也完全可以,行为和 0.1.0 一样,需要自己在 `beforeDestroy` 里调 `$destroy()`。
110
-
111
- ### 3. 页面内通信
112
-
113
- ```javascript
114
- // 组件 A —— 发射事件
115
- this.store.$emit('filter:change', newFilters);
116
-
117
- // 组件 B —— 监听事件
118
- const off = this.store.$on('filter:change', (filters) => {
119
- this.applyFilters(filters);
120
- });
121
-
122
- // 无需手动清理 —— $destroy 时自动回收
123
- ```
124
-
125
- ## 页面生命周期(0.2.0)
126
-
127
- 通过 `useStore(this)` 传入组件实例,store 会自动绑定到组件的生命周期:
128
-
129
- | 组件钩子 | store 行为 | `$status` 变化 |
130
- |----------|-----------|---------------|
131
- | `mounted` | 调用 `lifecycle.mount` | `mounted: true, active: true` |
132
- | `activated` | 调用 `lifecycle.activate` | `active: true` |
133
- | `deactivated` | 调用 `lifecycle.deactivate` | `active: false` |
134
- | `beforeDestroy` | 自动调 `$destroy()`,触发 `lifecycle.unmount` | `mounted: false, active: false` |
135
-
136
- ### 无 keep-alive
137
-
138
- ```
139
- mounted → lifecycle.mount → ... → beforeDestroy → lifecycle.unmount
140
- ```
141
-
142
- ### 有 keep-alive
143
-
144
- ```
145
- mounted → lifecycle.mount
146
- → deactivated → lifecycle.deactivate
147
- → activated → lifecycle.activate
148
- → deactivated → lifecycle.deactivate
149
- → activated → lifecycle.activate
150
- → ... 反复切换 ...
151
- → beforeDestroy → lifecycle.unmount
152
- ```
153
-
154
- ### keep-alive 示例
155
-
156
- ```javascript
157
- export const useListStore = definePageStore('listPage', {
158
- state: () => ({
159
- list: [],
160
- needRefresh: false,
161
- }),
162
-
163
- actions: {
164
- async fetchList() {
165
- this.list = await api.getList();
166
- this.needRefresh = false;
167
- },
168
- },
169
-
170
- lifecycle: {
171
- mount() {
172
- this.fetchList();
173
- },
174
- activate() {
175
- // 从缓存恢复时,按需刷新
176
- if (this.needRefresh) this.fetchList();
177
- },
178
- },
179
- });
180
- ```
181
-
182
- ### `$status` 响应式状态
183
-
184
- `$status` 是响应式对象,可以直接在模板中使用:
185
-
186
- ```html
187
- <template>
188
- <div v-if="store.$status.active">
189
- <!-- 页面激活时才渲染 -->
190
- </div>
191
- </template>
192
- ```
193
-
194
- ## API
195
-
196
- ### `definePageStore(id, options)`
197
-
198
- 定义一个页面级 Store,返回 `useStore` 函数。
199
-
200
- | 参数 | 类型 | 说明 |
201
- |------|------|------|
202
- | `id` | `string` | 唯一标识 |
203
- | `options.state` | `() => Object` | 返回初始 state 的工厂函数 |
204
- | `options.getters` | `Object` | 计算属性,`this` 指向 store |
205
- | `options.actions` | `Object` | 方法,`this` 指向 store |
206
- | `options.watch` | `Object` | 声明式侦听,支持点路径 `'a.b.c'` |
207
- | `options.lifecycle` | `Object` | 页面生命周期钩子 |
208
-
209
- ### `useStore(vm?)`
210
-
211
- 调用 `definePageStore` 返回的函数。
212
-
213
- | 用法 | 行为 |
214
- |------|------|
215
- | `useStore()` | 获取/创建 store,手动管理生命周期(兼容 0.1.0) |
216
- | `useStore(this)` | 获取/创建 store,自动绑定生命周期 + 自动销毁 |
217
-
218
- ### `lifecycle` 钩子
219
-
220
- | 钩子 | 触发时机 | `this` 指向 |
221
- |------|---------|------------|
222
- | `mount` | 组件 `mounted` | store |
223
- | `unmount` | 组件 `beforeDestroy`(`$destroy` 时触发) | store |
224
- | `activate` | 组件 `activated`(keep-alive 恢复) | store |
225
- | `deactivate` | 组件 `deactivated`(keep-alive 缓存) | store |
226
-
227
- ### Store 实例方法
228
-
229
- | 方法 | 说明 |
230
- |------|------|
231
- | `$patch(partial)` | 浅合并更新 state,接受对象或 `(state) => Object` 函数 |
232
- | `$reset()` | 重置 state 到初始值 |
233
- | `$emit(event, payload?)` | 发射事件(仅当前 store 作用域) |
234
- | `$on(event, handler)` | 订阅事件,返回取消函数 |
235
- | `$off(event, handler?)` | 取消事件订阅(不传 handler 则取消该事件全部监听) |
236
- | `$destroy()` | 销毁 store,回收所有资源 |
237
- | `bindTo(vm)` | 手动绑定到组件实例(通常不需要,`useStore(this)` 内部调用) |
238
-
239
- ### Store 实例属性
240
-
241
- | 属性 | 说明 |
242
- |------|------|
243
- | `$id` | store 唯一标识 |
244
- | `$state` | 原始响应式 state 对象 |
245
- | `$status` | 响应式对象 `{ mounted: boolean, active: boolean }` |
246
-
247
- ## 从 0.1.0 升级
248
-
249
- **零破坏性变更**。0.1.0 的代码不改一行也能跑。
250
-
251
- 区别只在于你现在可以把:
252
-
253
- ```javascript
254
- created() {
255
- this.store = useSomeStore();
256
- },
257
- beforeDestroy() {
258
- this.store.$destroy();
259
- }
260
- ```
261
-
262
- 简化成:
263
-
264
- ```javascript
265
- created() {
266
- this.store = useSomeStore(this);
267
- }
268
- ```
269
-
270
- > `storeToRefs` 和 `$subscribe` 在 0.2.0 中移除——实际项目中无使用场景,精简 API。
271
-
272
- ## 与 Pinia / Vuex 的关系
273
-
274
- 这不是 Pinia 或 Vuex 的替代品,而是补充:
275
-
276
- | | Vuex | Pinia | vue-page-store |
277
- |---|---|---|---|
278
- | 作用域 | 全局 | 全局 | 页面级 |
279
- | 生命周期 | 应用级 | 应用级 | 页面级(自动绑定) |
280
- | 事件通信 | 无 | 无 | 内置 $emit/$on |
281
- | Vue 2.6 支持 | ✅ | ⚠️ 需 @vue/composition-api | ✅ 原生支持 |
282
- | 适用场景 | 用户信息、权限、全局配置 | 同 Vuex | 复杂页面内部状态 |
283
-
284
- **推荐组合**:Vuex 管全局,vue-page-store 管页面。
285
-
286
- ## Vue 3
287
-
288
- 本库专为 Vue 2.6 设计。Vue 3 项目推荐使用 [Pinia](https://pinia.vuejs.org/)。
289
-
290
- ## License
291
-
1
+ # vue-page-store
2
+
3
+ > Vue 2.6 页面级 Store —— 状态、通信、生命周期,一个作用域全收。
4
+
5
+ ## 为什么需要它?
6
+
7
+ 在微前端架构(single-spa / qiankun)下,复杂页面(仪表盘、漏斗分析、数据详情)的状态管理面临一个尴尬处境:
8
+
9
+ | 方案 | 问题 |
10
+ |------|------|
11
+ | **Vuex** | 全局 store,页面销毁后状态残留,命名冲突,不适合页面级生命周期 |
12
+ | **全局 EventBus** | 命名冲突、手动 $off 容易遗漏、事件扩散到全局 |
13
+ | **provide / inject** | 只传数据,不管通信和副作用 |
14
+ | **组件 data** | 跨组件共享困难,深层传递 props 地狱 |
15
+
16
+ `vue-page-store` 解决的就是这个中间地带:**页面内部需要共享状态 + 通信 + 生命周期管理,但不应该污染全局。**
17
+
18
+ ## 核心特性
19
+
20
+ - **页面级作用域隔离** — 每个 store 独立一份 state 和事件,互不干扰
21
+ - **`useStore(this)` 一行绑定** — 自动挂载生命周期,自动销毁,零手动清理
22
+ - **页面生命周期** — `mount` / `unmount` / `activate` / `deactivate`,keep-alive 原生支持
23
+ - **API 对齐 Pinia** — `state` / `getters` / `actions` / `$patch` / `$reset`,零学习成本
24
+ - **内置作用域事件** — `$emit` / `$on` / `$off` 限定在当前 store 内,替代全局 EventBus
25
+ - **声明式 watch** — 页面级副作用自动绑定生命周期
26
+
27
+ ## 安装
28
+
29
+ ```bash
30
+ npm install vue-page-store
31
+ ```
32
+
33
+ > **前置条件**:项目中已安装 `vue@^2.6.0`
34
+
35
+ ## 快速上手
36
+
37
+ ### 1. 定义 Store
38
+
39
+ ```javascript
40
+ import { definePageStore } from 'vue-page-store';
41
+
42
+ export const useFunnelStore = definePageStore('funnelDetail', {
43
+ state: () => ({
44
+ filters: { dateRange: [], platform: '' },
45
+ loading: false,
46
+ funnelSteps: [],
47
+ }),
48
+
49
+ getters: {
50
+ isReady() {
51
+ return !this.loading && this.funnelSteps.length > 0;
52
+ },
53
+ },
54
+
55
+ actions: {
56
+ async fetchData() {
57
+ this.loading = true;
58
+ try {
59
+ this.funnelSteps = await api.getFunnelSteps(this.filters);
60
+ } finally {
61
+ this.loading = false;
62
+ }
63
+ },
64
+ },
65
+
66
+ watch: {
67
+ 'filters.platform'(newVal) {
68
+ this.fetchData();
69
+ },
70
+ },
71
+
72
+ // 0.2.0 新增:页面生命周期
73
+ lifecycle: {
74
+ mount() {
75
+ // 页面挂载时自动拉数据
76
+ this.fetchData();
77
+ },
78
+ unmount() {
79
+ console.log('页面销毁');
80
+ },
81
+ },
82
+ });
83
+ ```
84
+
85
+ ### 2. 组件中使用
86
+
87
+ ```javascript
88
+ export default {
89
+ created() {
90
+ // 传 this → 自动绑定生命周期 + 自动销毁,不需要 beforeDestroy
91
+ this.store = useFunnelStore(this);
92
+ },
93
+
94
+ computed: {
95
+ isReady() {
96
+ return this.store.isReady;
97
+ },
98
+ },
99
+
100
+ methods: {
101
+ handleSearch() {
102
+ this.store.$patch({ filters: this.localFilters });
103
+ this.store.fetchData();
104
+ },
105
+ },
106
+ };
107
+ ```
108
+
109
+ > **不传 `this`** 也完全可以,行为和 0.1.0 一样,需要自己在 `beforeDestroy` 里调 `$destroy()`。
110
+
111
+ ### 3. 页面内通信
112
+
113
+ ```javascript
114
+ // 组件 A —— 发射事件
115
+ this.store.$emit('filter:change', newFilters);
116
+
117
+ // 组件 B —— 监听事件
118
+ const off = this.store.$on('filter:change', (filters) => {
119
+ this.applyFilters(filters);
120
+ });
121
+
122
+ // 无需手动清理 —— $destroy 时自动回收
123
+ ```
124
+
125
+ ## 页面生命周期(0.2.0)
126
+
127
+ 通过 `useStore(this)` 传入组件实例,store 会自动绑定到组件的生命周期:
128
+
129
+ | 组件钩子 | store 行为 | `$status` 变化 |
130
+ |----------|-----------|---------------|
131
+ | `mounted` | 调用 `lifecycle.mount` | `mounted: true, active: true` |
132
+ | `activated` | 调用 `lifecycle.activate` | `active: true` |
133
+ | `deactivated` | 调用 `lifecycle.deactivate` | `active: false` |
134
+ | `beforeDestroy` | 自动调 `$destroy()`,触发 `lifecycle.unmount` | `mounted: false, active: false` |
135
+
136
+ ### 无 keep-alive
137
+
138
+ ```
139
+ mounted → lifecycle.mount → ... → beforeDestroy → lifecycle.unmount
140
+ ```
141
+
142
+ ### 有 keep-alive
143
+
144
+ ```
145
+ mounted → lifecycle.mount
146
+ → deactivated → lifecycle.deactivate
147
+ → activated → lifecycle.activate
148
+ → deactivated → lifecycle.deactivate
149
+ → activated → lifecycle.activate
150
+ → ... 反复切换 ...
151
+ → beforeDestroy → lifecycle.unmount
152
+ ```
153
+
154
+ ### keep-alive 示例
155
+
156
+ ```javascript
157
+ export const useListStore = definePageStore('listPage', {
158
+ state: () => ({
159
+ list: [],
160
+ needRefresh: false,
161
+ }),
162
+
163
+ actions: {
164
+ async fetchList() {
165
+ this.list = await api.getList();
166
+ this.needRefresh = false;
167
+ },
168
+ },
169
+
170
+ lifecycle: {
171
+ mount() {
172
+ this.fetchList();
173
+ },
174
+ activate() {
175
+ // 从缓存恢复时,按需刷新
176
+ if (this.needRefresh) this.fetchList();
177
+ },
178
+ },
179
+ });
180
+ ```
181
+
182
+ ### `$status` 响应式状态
183
+
184
+ `$status` 是响应式对象,可以直接在模板中使用:
185
+
186
+ ```html
187
+ <template>
188
+ <div v-if="store.$status.active">
189
+ <!-- 页面激活时才渲染 -->
190
+ </div>
191
+ </template>
192
+ ```
193
+
194
+ ## API
195
+
196
+ ### `definePageStore(id, options)`
197
+
198
+ 定义一个页面级 Store,返回 `useStore` 函数。
199
+
200
+ | 参数 | 类型 | 说明 |
201
+ |------|------|------|
202
+ | `id` | `string` | 唯一标识 |
203
+ | `options.state` | `() => Object` | 返回初始 state 的工厂函数 |
204
+ | `options.getters` | `Object` | 计算属性,`this` 指向 store |
205
+ | `options.actions` | `Object` | 方法,`this` 指向 store |
206
+ | `options.watch` | `Object` | 声明式侦听,支持点路径 `'a.b.c'` |
207
+ | `options.lifecycle` | `Object` | 页面生命周期钩子 |
208
+
209
+ ### `useStore(vm?)`
210
+
211
+ 调用 `definePageStore` 返回的函数。
212
+
213
+ | 用法 | 行为 |
214
+ |------|------|
215
+ | `useStore()` | 获取/创建 store,手动管理生命周期(兼容 0.1.0) |
216
+ | `useStore(this)` | 获取/创建 store,自动绑定生命周期 + 自动销毁 |
217
+
218
+ ### `lifecycle` 钩子
219
+
220
+ | 钩子 | 触发时机 | `this` 指向 |
221
+ |------|---------|------------|
222
+ | `mount` | 组件 `mounted` | store |
223
+ | `unmount` | 组件 `beforeDestroy`(`$destroy` 时触发) | store |
224
+ | `activate` | 组件 `activated`(keep-alive 恢复) | store |
225
+ | `deactivate` | 组件 `deactivated`(keep-alive 缓存) | store |
226
+
227
+ ### Store 实例方法
228
+
229
+ | 方法 | 说明 |
230
+ |------|------|
231
+ | `$patch(partial)` | 浅合并更新 state,接受对象或 `(state) => Object` 函数 |
232
+ | `$reset()` | 重置 state 到初始值 |
233
+ | `$emit(event, payload?)` | 发射事件(仅当前 store 作用域) |
234
+ | `$on(event, handler)` | 订阅事件,返回取消函数 |
235
+ | `$off(event, handler?)` | 取消事件订阅(不传 handler 则取消该事件全部监听) |
236
+ | `$destroy()` | 销毁 store,回收所有资源 |
237
+ | `bindTo(vm)` | 手动绑定到组件实例(通常不需要,`useStore(this)` 内部调用) |
238
+
239
+ ### Store 实例属性
240
+
241
+ | 属性 | 说明 |
242
+ |------|------|
243
+ | `$id` | store 唯一标识 |
244
+ | `$state` | 原始响应式 state 对象 |
245
+ | `$status` | 响应式对象 `{ mounted: boolean, active: boolean }` |
246
+
247
+ ## 从 0.1.0 升级
248
+
249
+ **零破坏性变更**。0.1.0 的代码不改一行也能跑。
250
+
251
+ 区别只在于你现在可以把:
252
+
253
+ ```javascript
254
+ created() {
255
+ this.store = useSomeStore();
256
+ },
257
+ beforeDestroy() {
258
+ this.store.$destroy();
259
+ }
260
+ ```
261
+
262
+ 简化成:
263
+
264
+ ```javascript
265
+ created() {
266
+ this.store = useSomeStore(this);
267
+ }
268
+ ```
269
+
270
+ > `storeToRefs` 和 `$subscribe` 在 0.2.0 中移除——实际项目中无使用场景,精简 API。
271
+
272
+ ## 与 Pinia / Vuex 的关系
273
+
274
+ 这不是 Pinia 或 Vuex 的替代品,而是补充:
275
+
276
+ | | Vuex | Pinia | vue-page-store |
277
+ |---|---|---|---|
278
+ | 作用域 | 全局 | 全局 | 页面级 |
279
+ | 生命周期 | 应用级 | 应用级 | 页面级(自动绑定) |
280
+ | 事件通信 | 无 | 无 | 内置 $emit/$on |
281
+ | Vue 2.6 支持 | ✅ | ⚠️ 需 @vue/composition-api | ✅ 原生支持 |
282
+ | 适用场景 | 用户信息、权限、全局配置 | 同 Vuex | 复杂页面内部状态 |
283
+
284
+ **推荐组合**:Vuex 管全局,vue-page-store 管页面。
285
+
286
+ ## Vue 3
287
+
288
+ 本库专为 Vue 2.6 设计。Vue 3 项目推荐使用 [Pinia](https://pinia.vuejs.org/)。
289
+
290
+ ## License
291
+
292
292
  [MIT](./LICENSE)