Skip to content

Commit

Permalink
feat: 添加 VuexStoreHelper概念
Browse files Browse the repository at this point in the history
 - 修正 深层 getter 取值
  • Loading branch information
imsunhao committed Aug 21, 2019
1 parent bcf5aa4 commit 40e85a6
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 65 deletions.
73 changes: 55 additions & 18 deletions doc/@types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,60 @@ declare namespace Doc {
}
}
}
/**
* vuex getters
*/
interface getters {
/**
* 是否 使用 移动设备 访问
* * 来自服务器端
* * 这是一个例子
*/
isMobile: boolean

/**
* 是否 使用 移动设备 访问
* * 来自 中间件-服务器端
* * 这是一个例子
*/
hello: string

/**
* 测试 热加载 vuex
* * 来自 客户端
* * 这是一个例子
*/
testHotLoadingVuex: number

/**
* 初始化 跳转访问 URL
* * 来自服务器端
* * 这是一个例子
*/
initialReplaceStateUrl: string

/**
* 编辑器
*/
editor?: {
test: string
deepTest: {
test1: string
test2: number
}
}

/**
* 单元测试使用
*/
test?: {
test: string
deepTest: {
test1: string
test2: number
}
}
}

/**
* vuex Mutation-tree
Expand Down Expand Up @@ -140,21 +194,4 @@ declare namespace Doc {
}
}

export = Doc

import { ActionTree, Store, MutationTree } from 'vuex'
/**
* vuex 创建 工具函数
* * typescript namespace
*/
export namespace CreateVuex {
type SniffMutationPayload<T> = T extends (state: any, payload: infer P) => any ? P : T
type SniffMutationPayloadTree<S, M extends MutationTree<S>> = { [K in keyof M]: SniffMutationPayload<M[K]> }
type SniffActionPayload<T> = T extends (state: any, payload: infer P) => infer V
? { payload: P; value: V }
: { payload: unknown; value: unknown }
type SniffActionPayloadTree<S, M extends ActionTree<S, Tstore.state>> = { [K in keyof M]: SniffActionPayload<M[K]> }
type SniffActionPayloadPathTree<S, M extends ActionTree<S, Tstore.state>> = {
[K in keyof M]: SniffMutationPayload<M[K]>
}
}
export = Doc
2 changes: 2 additions & 0 deletions doc/src/store/editor/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const VUEX_NS = 'editor'
export type VUEX_NS = typeof VUEX_NS
10 changes: 7 additions & 3 deletions doc/src/store/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { Tstore } from '@types'
import { makeWrapper } from 'src/store/utils'
import { VuexStoreHelper } from 'src/store/utils'

export const globalHelper = makeWrapper<Tstore.state>()
export const editorHelper = makeWrapper<Tstore.state['editor']>('editor')
import { VUEX_NS as editor } from 'src/store/editor'

const { makeWrapper } = new VuexStoreHelper<Tstore.state, Tstore.getters>()

export const globalHelper = makeWrapper()
export const editorHelper = makeWrapper<Tstore.state[editor], Tstore.getters[editor]>(editor)

/**
* 例子 1
Expand Down
81 changes: 38 additions & 43 deletions doc/src/store/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
import { ActionTree, Store, MutationTree, ActionContext } from 'vuex'

export class VuexHelper<GlobalStates, GlobalGetters> {
makeWrapper<T, G extends { [k in string]: any }>(namespace: keyof GlobalStates | string[] = ('' as any)) {
function isStore(context: Store<any>) {
return 'strict' in context
}

function checkStore(context: any, { namespace, args }) {
if (isStore(context)) {
checkNamespace(namespace, args)
}
}

function checkNamespace(namespace: string[], args: any[]) {
// TODO: 完善深层namespace解析
if (namespace) {
if (typeof namespace === 'string') {
args.unshift(namespace)
} else {
namespace = [ ...namespace ]
namespace.reverse().forEach(key => {
args.unshift(key)
})
}
}
}

export class VuexStoreHelper<GlobalStates, GlobalGetters> {
makeWrapper<T = GlobalStates, G = GlobalGetters>(namespace: keyof GlobalStates | string[] = ('' as any)) {
type SniffMutationPayload<T> = T extends (state: any, payload: infer P) => any ? P : T
type SniffMutationPayloadTree<S, M extends MutationTree<S>> = { [K in keyof M]: SniffMutationPayload<M[K]> }
type SniffActionPayload<T> = T extends (state: any, payload: infer P) => infer V
Expand All @@ -15,8 +39,7 @@ export class VuexHelper<GlobalStates, GlobalGetters> {
type GetterTree = {
[K in keyof G]: (state: T, getters: G, rootState: GlobalStates, rootGetters: GlobalGetters) => G[K]
}

const GetterTree: GetterTree = undefined as any
type TActionTree = ActionTree<T, GlobalStates>

function createGetState() {
function getState<P extends keyof T>(
Expand All @@ -42,7 +65,7 @@ export class VuexHelper<GlobalStates, GlobalGetters> {
path3: P3,
): T[P][P1][P2][P3]
function getState(context: TActionContext, ...args: string[]) {
this.checkStore(context, { namespace, args })
checkStore(context, { namespace, args })
let result
for (let index = 0; index < args.length; index++) {
const key = args[index]
Expand Down Expand Up @@ -79,19 +102,17 @@ export class VuexHelper<GlobalStates, GlobalGetters> {
path3: P3,
): G[P][P1][P2][P3]
function getGetter(context: TActionContext, ...args: string[]) {
this.checkStore(context, { namespace, args })
let result
for (let index = 0; index < args.length; index++) {
const key = args[index]
if (!result) result = context.getters[key]
else result = result[key]
if (!result) return
}
return result
checkStore(context, { namespace, args })
const paths = args.join('/')
return context.getters[paths]
}
return getGetter
}

function makeGetters(getters: GetterTree) {
return getters
}

function makeMutations<M extends MutationTree<T>>(mutationTree: M) {
return mutationTree
}
Expand Down Expand Up @@ -125,7 +146,7 @@ export class VuexHelper<GlobalStates, GlobalGetters> {
payload: SniffMutationPayloadTree<T, MutationPayloadTree[P][P1][P2]>[M],
): void
function commit(context: TActionContext, ...args: any[]) {
this.checkStore(context, { namespace, args })
checkStore(context, { namespace, args })
if (args.length < 2) {
console.error('commit args.length must > 2')
return
Expand All @@ -138,8 +159,6 @@ export class VuexHelper<GlobalStates, GlobalGetters> {
return commit
}

type TActionTree = ActionTree<T, GlobalStates>

function makeActions<A extends TActionTree>(actionTree: A) {
return actionTree
}
Expand Down Expand Up @@ -174,7 +193,7 @@ export class VuexHelper<GlobalStates, GlobalGetters> {
payload: SniffActionPayloadTree<ActionPayloadPathTree[P], AT>[M]['payload'],
): SniffActionPayloadTree<ActionPayloadPathTree[P], AT>[M]['value']
function dispatch(context: TActionContext, ...args: any[]): any {
this.checkStore(context, { namespace, args })
checkStore(context, { namespace, args })
if (args.length < 2) {
console.error('commit args.length must > 2')
return
Expand All @@ -188,37 +207,13 @@ export class VuexHelper<GlobalStates, GlobalGetters> {
}

return {
GetterTree,
createGetState,
createGetGetter,
makeGetters,
makeMutations,
createCommit,
makeActions,
createDispatch,
}
}

private isStore(context: Store<any>) {
return 'strict' in context
}

protected checkStore(context: any, { namespace, args }) {
if (this.isStore(context)) {
this.checkNamespace(namespace, args)
}
}

protected checkNamespace(namespace: keyof GlobalStates | string[], args: any[]) {
// TODO: 完善深层namespace解析
if (namespace) {
if (typeof namespace === 'string') {
args.unshift(namespace)
} else {
namespace = [ ...namespace ]
namespace.reverse().forEach(key => {
args.unshift(key)
})
}
}
}
}
4 changes: 3 additions & 1 deletion doc/tests/unit/store/base-utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
import { makeWrapper } from 'src/store/utils'
import { VuexStoreHelper } from 'src/store/utils'
import { merge } from 'lodash'

/**
Expand Down Expand Up @@ -75,6 +75,7 @@ namespace Tstore {
}
}
}
const { makeWrapper } = new VuexStoreHelper<Tstore.state, Tstore.getters>()

describe('Vux base-utils.spec', () => {
const defalutTestString = 'defalutTestString'
Expand Down Expand Up @@ -113,6 +114,7 @@ describe('Vux base-utils.spec', () => {
},
})
const getState = globalHelper.createGetState()
const getGetter = globalHelper.createGetGetter()
const commit = globalHelper.createCommit<typeof mutations>()

it('commit getState', () => {
Expand Down

0 comments on commit 40e85a6

Please sign in to comment.