diff --git a/src/@types/index.d.ts b/src/@types/index.d.ts index 02e5e5a..1bc27c0 100644 --- a/src/@types/index.d.ts +++ b/src/@types/index.d.ts @@ -1,2 +1,15 @@ -type ComponentOptions = WechatMiniprogram.Component.Options -type PageOptions = WechatMiniprogram.Page.Options \ No newline at end of file +type DataOption = Record +type CustomOption = Record +type PropertyOption = Record +type MethodOption = Record any> + +type PageOptions< + TData extends DataOption, + TCustom extends CustomOption +> = WechatMiniprogram.Page.Options + +type ComponentOptions< + TData extends DataOption, + TProperty extends PropertyOption, + TMethod extends MethodOption +> = WechatMiniprogram.Component.Options diff --git a/src/create.ts b/src/create.ts deleted file mode 100644 index 51b8c1e..0000000 --- a/src/create.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { autorun, IReactionDisposer } from 'mobx' -import { is } from './utils' -import diff from './diff' - -const create = { - page: (stores: AnyObject, mapper: Function, options: PageOptions) => { - let dispose: IReactionDisposer - - const { data = {}, onLoad, onUnload } = options - - return Page({ - ...options, - data: { ...data, ...mapper(stores) }, - - onLoad(query) { - dispose = autorun(() => { - if (this.data) { - const diffs: AnyObject = diff({ ...this.data, ...mapper(stores) }, this.data) - - for (const key in diffs) { - if (key) this.setData({ [key]: diffs[key] }) - } - } - }) - - if (is.fun(onLoad)) onLoad.call(this, query) - }, - - onUnload() { - if (dispose) dispose() - - if (is.fun(onUnload)) onUnload.call(this) - }, - }) - }, - - component(stores: AnyObject, mapper: Function, options: ComponentOptions) { - let dispose: IReactionDisposer - - const { data = {}, attached, detached } = options - - return Component({ - ...options, - data: { ...data, ...mapper(stores) }, - - attached() { - dispose = autorun(() => { - if (this.data) { - const diffs: AnyObject = diff({ ...this.data, ...mapper(stores) }, this.data) - - for (const key in diffs) { - if (key) this.setData({ [key]: diffs[key] }) - } - } - }) - - if (is.fun(attached)) attached.call(this) - }, - - detached() { - if (dispose) dispose() - - if (is.fun(detached)) detached.call(this) - }, - }) - }, -} - -export default create diff --git a/src/inject.ts b/src/inject.ts index dd80588..8aa3938 100644 --- a/src/inject.ts +++ b/src/inject.ts @@ -1,28 +1,22 @@ -import create from './create' -import { toData } from './utils' +const mapStores = (names: (keyof TStores)[]) => (source: TStores) => { + const target: TStores = {} as TStores -const mapStores = (names: string[]) => (source: AnyObject) => { - const target: AnyObject = {} - - names.forEach((key) => { + names.forEach(key => { if (source && source[key]) { - target[key] = toData(source[key]) + target[key] = source[key] } }) return target } -const inject = { - page: (...storeNames: string[]) => ( - createOptions: (stores: AnyObject) => PageOptions - ) => - create.page(getApp().stores, mapStores(storeNames), createOptions(getApp().stores)), +const inject = (...storeNames: (keyof TStores)[]) => ( + createObserver: (stores: TStores) => (observedStores: AnyObject) => void | string +) => { + const stores = getApp().stores ?? {} + const observedStores = mapStores(storeNames)(stores) - component: (...storeNames: string[]) => ( - createOptions: (stores: AnyObject) => ComponentOptions - ) => - create.component(getApp().stores, mapStores(storeNames), createOptions(getApp().stores)), + return createObserver(stores)(observedStores) } export default inject diff --git a/src/observer.ts b/src/observer.ts index 3abecbe..552edab 100644 --- a/src/observer.ts +++ b/src/observer.ts @@ -1,12 +1,75 @@ -import create from './create' -import { toData } from './utils' +import { autorun, IReactionDisposer } from 'mobx' +import { is, toData } from './utils' +import diff from './diff' const observer = { - page: (stores: AnyObject) => (options: PageOptions) => - create.page(stores, toData, options), + page: ( + options: PageOptions + ) => { + let dispose: IReactionDisposer - component: (stores: AnyObject) => (options: ComponentOptions) => - create.component(stores, toData, options), + const { data = {}, onLoad, onUnload } = options + + return (observedStores: AnyObject = {}) => + Page({ + ...options, + data: { ...data, ...toData(observedStores) }, + + onLoad(query) { + dispose = autorun(() => { + if (this.data) { + const diffs: AnyObject = diff({ ...this.data, ...toData(observedStores) }, this.data) + + this.setData(diffs) + } + }) + + if (is.fun(onLoad)) onLoad.call(this, query) + }, + + onUnload() { + if (dispose) dispose() + + if (is.fun(onUnload)) onUnload.call(this) + }, + }) + }, + + component: < + TData extends DataOption, + TProperty extends PropertyOption, + TMethod extends MethodOption + >( + options: ComponentOptions + ) => { + let dispose: IReactionDisposer + + const { data = {}, attached, detached } = options + + return (observedStores: AnyObject = {}) => + Component({ + ...options, + data: { ...data, ...toData(observedStores) }, + + attached() { + dispose = autorun(() => { + if (this.data) { + const diffs: AnyObject = diff({ ...this.data, ...toData(observedStores) }, this.data) + + this.setData(diffs) + } + }) + + if (is.fun(attached)) attached.call(this) + }, + + detached() { + if (dispose) dispose() + + if (is.fun(detached)) detached.call(this) + }, + }) + }, } export default observer diff --git a/src/provider.ts b/src/provider.ts index 2f5e78a..2910691 100644 --- a/src/provider.ts +++ b/src/provider.ts @@ -1,6 +1,7 @@ -type AppOptions = WechatMiniprogram.App.Options +type AppOptions = WechatMiniprogram.App.Options -const provider = (stores: T) => (options: AppOptions) => - App({ ...options, stores }) +const provider = (stores: TStores) => ( + options: AppOptions +) => App({ ...options, stores }) export default provider