From 7365ccf00e03a50c8ca5fa3804b0aaca8071c2b0 Mon Sep 17 00:00:00 2001 From: sunhao Date: Mon, 29 Jul 2019 15:15:58 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20vuex=20Action=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E5=85=A8=E5=B1=80=20dispatch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/@types/index.d.ts | 70 +++++++++++++++++++++++++-------------- doc/src/store/actions.ts | 20 ++++++++++- doc/src/store/index.ts | 4 +-- doc/src/store/utils.ts | 71 ++++++++++++++++++++++------------------ doc/tsconfig.json | 2 +- 5 files changed, 106 insertions(+), 61 deletions(-) diff --git a/doc/@types/index.d.ts b/doc/@types/index.d.ts index d517190..d109150 100644 --- a/doc/@types/index.d.ts +++ b/doc/@types/index.d.ts @@ -1,7 +1,12 @@ -import { Store } from 'vuex' -import { TMutations as GlobalMutations } from 'src/store/mutations' - +/** + * Doc 全局类型 + * * typescript namespace + */ declare namespace Doc { + import { Store } from 'vuex' + import { TMutations as GlobalMutations } from 'src/store/mutations' + import { TActions as GlobalActions } from 'src/store/actions' + type DictOf = { [key: string]: T } /** @@ -9,28 +14,6 @@ declare namespace Doc { * * typescript namespace */ namespace Tstore { - /** - * vuex 创建 工具函数 - * * typescript namespace - */ - namespace createUtils { - type ActionDescriptor = [any, any] - - /** - * 用于声明 Actions Descriptors - */ - type ActionsOfDescriptors> = { - [K in keyof Descriptor]: (ctx: Context, payload: Descriptor[K][0]) => Descriptor[K][1] - } - - /** - * 用于声明 Mutations - */ - type ModuleMutations = { - [K in keyof PayloadTree]: (state: State, payload: PayloadTree[K]) => any - } - } - /** * vuex state */ @@ -94,6 +77,26 @@ declare namespace Doc { } } } + + /** + * vuex Action-tree + */ + type Actions = GlobalActions & { + /** + * 编辑器 + */ + editor: GlobalActions & { + /** + * 编辑器 + */ + editor2: GlobalActions & { + /** + * 编辑器 + */ + editor3: GlobalActions + } + } + } } /** @@ -126,3 +129,20 @@ declare namespace Doc { } export = Doc + +/** + * vuex 创建 工具函数 + * * typescript namespace + */ +export namespace CreateVuex { + import { ActionTree, Store, MutationTree } from 'vuex' + type SniffMutationPayload = T extends (state: any, payload: infer P) => any ? P : T + type SniffMutationPayloadTree> = { [K in keyof M]: SniffMutationPayload } + type SniffActionPayload = T extends (state: any, payload: infer P) => infer V + ? { payload: P; value: V } + : { payload: unknown; value: unknown } + type SniffActionPayloadTree> = { [K in keyof M]: SniffActionPayload } + type SniffActionPayloadPathTree> = { + [K in keyof M]: SniffMutationPayload + } +} \ No newline at end of file diff --git a/doc/src/store/actions.ts b/doc/src/store/actions.ts index 4400f5a..fc0f6cd 100644 --- a/doc/src/store/actions.ts +++ b/doc/src/store/actions.ts @@ -1,4 +1,5 @@ import { globalHelper } from 'src/store/helpers' +import { Tstore } from '@types' export const actions = globalHelper.makeActions({ GET_SERVER_DATA(ctx, { id }: { id: number }) { @@ -15,11 +16,28 @@ export const actions = globalHelper.makeActions({ export default actions -export const dispatch = globalHelper.createDispatch() +export type TActions = typeof actions + +export const dispatch = globalHelper.createDispatch() // const store = this.store // dispatch(store, 'GET_SERVER_DATA', { id: 1 }).then(({ id }) => { // id = 'st' // id = 1 +// }) + +// dispatch(store, 'editor', 'GET_SERVER_DATA', { id: 1 }).then(({ id }) => { +// id = 'st' +// id = 1 +// }) + +// dispatch(store, 'editor', 'editor2', 'GET_SERVER_DATA', { id: 1 }).then(({ id }) => { +// id = 'st' +// id = 1 +// }) + +// dispatch(store, 'editor', 'editor2', 'editor3', 'GET_SERVER_DATA', { id: 1 }).then(({ id }) => { +// id = 'st' +// id = 1 // }) \ No newline at end of file diff --git a/doc/src/store/index.ts b/doc/src/store/index.ts index 10235c9..384e3e7 100644 --- a/doc/src/store/index.ts +++ b/doc/src/store/index.ts @@ -2,7 +2,7 @@ import { Tstore } from '@types' import Vue from 'vue' import Vuex from 'vuex' -import actions from './actions' +import actions, { dispatch } from './actions' import mutations, { commit, getState } from './mutations' import getters from './getters' import state from './state' @@ -19,4 +19,4 @@ export function createStore() { }) } -export { commit, getState } \ No newline at end of file +export { commit, getState, dispatch } \ No newline at end of file diff --git a/doc/src/store/utils.ts b/doc/src/store/utils.ts index 9a69a1a..032bdd0 100644 --- a/doc/src/store/utils.ts +++ b/doc/src/store/utils.ts @@ -1,18 +1,7 @@ -import { Tstore } from '@types' +import { Tstore, CreateVuex } from '@types' import { ActionTree, Store, MutationTree } from 'vuex' -export type SniffMutationPayload = T extends (state: any, payload: infer P) => any ? P: T -export type SniffMutationPayloadTree> = { - [K in keyof M]: SniffMutationPayload -} - -export type SniffActionPayload = T extends (state: any, payload: infer P) => infer V ? { payload: P, value: V }: { payload: unknown, value: unknown } -export type SniffActionPayloadTree> = { - [K in keyof M]: SniffActionPayload -} - export function makeWrapper(namespace: keyof Tstore.state = ('' as any)) { - function createGetState() { function getState( context: Store, @@ -37,8 +26,7 @@ export function makeWrapper(namespace: keyof Tstore.state = ('' as any)) { state3Key: K3, ): T[K][K1][K2][K3] function getState(context: Store, ...args: string[]) { - if (!checkStore(context)) return - checkNamespace(namespace, args) + checkStore(context, { namespace, args }) let result for (let index = 0; index < args.length; index++) { const key = args[index]; @@ -56,7 +44,7 @@ export function makeWrapper(namespace: keyof Tstore.state = ('' as any)) { } function createCommit>() { - type MutationPayloadTree = SniffMutationPayloadTree + type MutationPayloadTree = CreateVuex.SniffMutationPayloadTree function commit( context: Store, mutation: M, @@ -66,14 +54,14 @@ export function makeWrapper(namespace: keyof Tstore.state = ('' as any)) { context: Store, path: P, mutation: M, - payload: SniffMutationPayloadTree[M], + payload: CreateVuex.SniffMutationPayloadTree[M], ): void function commit

( context: Store, path: P, path1: P1, mutation: M, - payload: SniffMutationPayloadTree[M], + payload: CreateVuex.SniffMutationPayloadTree[M], ): void function commit

( context: Store, @@ -81,15 +69,14 @@ export function makeWrapper(namespace: keyof Tstore.state = ('' as any)) { path1: P1, path2: P2, mutation: M, - payload: SniffMutationPayloadTree[M], + payload: CreateVuex.SniffMutationPayloadTree[M], ): void function commit(context: Store, ...args: any[]) { - if (!checkStore(context)) return + checkStore(context, { namespace, args }) if (args.length < 2) { console.error('commit args.length must > 2') return } - checkNamespace(namespace, args) const payload = args.pop() const paths = args.join('/') return context.commit(paths, payload) @@ -104,20 +91,41 @@ export function makeWrapper(namespace: keyof Tstore.state = ('' as any)) { return actionTree } - function createDispatch() { - type actionPayloadTree = SniffActionPayloadTree - function dispatch( + function createDispatch() { + type ActionPayloadPathTree = CreateVuex.SniffActionPayloadPathTree + type ActionPayloadTree = CreateVuex.SniffActionPayloadTree + function dispatch( context: Store, type: M, - payload: actionPayloadTree[M]['payload'], - ): actionPayloadTree[M]['value'] + payload: ActionPayloadTree[M]['payload'], + ): ActionPayloadTree[M]['value'] + function dispatch

( + context: Store, + path: P, + type: M, + payload: CreateVuex.SniffActionPayloadTree[M]['payload'], + ): CreateVuex.SniffActionPayloadTree[M]['value'] + function dispatch

( + context: Store, + path: P, + path1: P1, + type: M, + payload: CreateVuex.SniffActionPayloadTree[M]['payload'], + ): CreateVuex.SniffActionPayloadTree[M]['value'] + function dispatch

( + context: Store, + path: P, + path1: P1, + path2: P2, + type: M, + payload: CreateVuex.SniffActionPayloadTree[M]['payload'], + ): CreateVuex.SniffActionPayloadTree[M]['value'] function dispatch(context: Store, ...args: any[]): any { - if (!checkStore(context)) return + checkStore(context, { namespace, args }) if (args.length < 2) { console.error('commit args.length must > 2') return } - checkNamespace(namespace, args) const payload = args.pop() const paths = args.join('/') return context.dispatch(paths, payload) @@ -139,15 +147,14 @@ function isStore(context: Store) { return 'strict' in context } -function checkStore(context: Store) { - if (!isStore(context)) { - console.error('checkStore context is not a vuex store!', context) - return false +function checkStore(context: Store, { namespace, args }) { + if (isStore(context)) { + checkNamespace(namespace, args) } - return true } function checkNamespace(namespace: keyof Tstore.state, args: any[]) { + // TODO: 完善深层namespace解析 if (namespace) { args.unshift(namespace) } diff --git a/doc/tsconfig.json b/doc/tsconfig.json index d2eed66..1672db1 100644 --- a/doc/tsconfig.json +++ b/doc/tsconfig.json @@ -24,6 +24,6 @@ "keyofStringsOnly": true, "lib": ["dom", "es5", "es6", "scripthost", "es2018.promise", "webworker"] }, - "include": ["tests", "src", "server", "src/**/*.vue", "@types/*"], + "include": ["tests", "src", "server", "src/**/*.vue", "@types"], "exclude": ["node_modules", "*node_modules*", "dist", "docs", ".tmp", "build"] }