-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
如何创建一个模块的多个实例? #430
Comments
Sigi 可以这样做但是不鼓励这样做。一个模块的多个实例在使用上会造成很多概念不一致的问题。
后续会做这件事情 |
假设我要在页面上做文件拷贝, 有一个 另外, Sigi 和自行封装 Vuex 的动态模块, 除了框架无关外还有哪些优势呢(除了RxJS本身带来的优势之外)? |
因为 Sigi 的 Module 上 state = {
page1: FolderExploerDefaultState,
page2: FolderExploerDefaultState,
} 然后在组件调用 dispatcher 的时候传入各自的 namespace
然后在 Effect/Reducer 里面分别处理 @Effect()
update(payload$: Observable<{ page: 'page1' | 'page2', value ... }>) {
return payload$.pipe(
exhaustMap(({ page, value }) => {
return this.fetch(...value).pipe(
map((res) => this.getActions().updatePage({ page, res }))
)
})
)
}
除了 |
不太明白这样做的意思, 感觉更复杂了. 其实本来 或许这种场景应该用纯粹的 react hooks 或其它组件框架相关的技术, Sigi 只该用在需要状态共享的地方? |
非单例模块在注入到其它模块的时候会有歧义。
其实就是 follow redux 的设计,redux 单一 store 也是通过在 store 里面加 namespace 来区分相同"形状"的不同模块 |
// App
<div>
<SigiMultiFolderExplorer />
<SigiFolderExplorer />
</div>
// SigiFolderExplorer
import { useModule, useModuleState } from '@sigi/react'
import { FolderExplorerModule } from './folder-explorer.module'
export default ({ actived }) => {
const [state, dispatcher] = useModule(FolderExplorerModule )
return (
<DummyFolderExplorer {...state} actived onChange={dispatcher.update} />
)
}
// SigiMultiFolderExplorer
// SigiMultiFolderExplorer 中 item 自身的状态该由谁管理 ?
// 如果是 SigiMultiFolderExplorer 自身管理, 如何复用 SigiFolderExplorer 组件 ?
// 如果是 SigiFolderExplorer 管理, 如何让所有 SigiFolderExplorer 中的状态独立 ?
import { useModule, useModuleState } from '@sigi/react'
import SigiFolderExplorer from './SigiFolderExplorer '
import { MultiFolderExplorerState } from './multi-folder-explorer.module'
export default () => {
const [state, dispatcher] = useModule(MultiFolderExplorerState)
return (
<div>
copy files in {state.explorer1.currentPath} to {state.explorer2.currentPath}
// <SigiFolderExplorer actived={state.actived === 'explorer1'} />
// <SigiFolderExplorer actived={state.actived === 'explorer2'} />
<DummyFolderExplorer {...state.explorer1} onChange={dispatcher.updateExplorer1} />
<DummyFolderExplorer {...state.explorer2} onChange={dispatcher.updateExplorer2} />
</div>
)
}
// folder-explorer.module
@Module("FolderExplorer")
export class FolderExplorerModule extends EffectModule<FolderExplorerState> {
defaultState: FolderExplorerState= {
currentPath: '',
// ...
};
constructor(
private readonly appService: AppService,
private readonly appModule: AppModule,
private readonly authModule: AuthModule,
// ...
) {
super();
}
}
// multi-folder-explorer.module
@Module("MultiFolderExplorer")
export class MultiFolderExplorerModule extends EffectModule<MultiFolderExplorerState> {
defaultState: MultiFolderExplorerState= {
// 应该在这里管理 item 的状态 ?
// 如果在这里管理, 则需要在这里重写一遍 folder-explorer.module 中 的 reducer/effect
explorer1: FolderExploerDefaultState,
explorer2: FolderExploerDefaultState,
actived: 'explorer1',
// ...
};
constructor(
private readonly appService: AppService,
private readonly appModule: AppModule,
private readonly authModule: AuthModule,
// ...
) {
super();
}
} 不知道这样能否表达清楚. 你上面提到的:
这种做法, 我没理解错的话就是要在 multi-folder-explorer.module 中重写一遍 folder-explorer.module 中 的 reducer/effect. |
大概这样封装,FolderExplorerModule 存所有 explorer 的状态,Effect/Reducer 通过组件传进来的 Explorer 来决定更新哪一个状态,所以 Effect/Reducer 是完全复用的。Redux 在这种场景下也是一样的用法,复用 reducer/effect 就得在参数上区分更新哪一个部分的状态,渲染的时候通过 selector 选择渲染需要的那一小部分数据。 // App
<div>
<SigiMultiFolderExplorer />
<SigiFolderExplorer />
</div>
// SigiFolderExplorer
import { useModule, useModuleState } from '@sigi/react'
import { FolderExplorerModule } from './folder-explorer.module'
export default ({ actived }) => {
const [state, dispatcher] = useModule(FolderExplorerModule, {
selector: (state) => state[actived],
dependencies: [actived]
})
const update = useCallback((actived) => {
(updated: FolderUpdated) => dispatcher.update({ explorer: actived, updated })
}, [actived, dispatcher])
return (
<DummyFolderExplorer {...state} actived onChange={update} />
)
}
import { useModule, useModuleState } from '@sigi/react'
import SigiFolderExplorer from './SigiFolderExplorer '
import { MultiFolderExplorerState } from './multi-folder-explorer.module'
import { FolderExplorerModule } from './folder-explorer.module'
export default () => {
const [state, dispatcher] = useModule(MultiFolderExplorerState)
const [folderState, folderDispatcher] = useModule(FolderExplorerModule)
const updateExplorer = useCallback((explorer: string) => {
return (changed: FolderChanged) => folderDispatcher.updateExplorer({ explorer, changed })
}, [folderDispatcher])
return (
<div>
copy files in {state.explorer1.currentPath} to {state.explorer2.currentPath}
<DummyFolderExplorer {...folderState.explorer1} onChange={updateExplorer(explorer1)} />
<DummyFolderExplorer {...folderState.explorer2} onChange={updateExplorer(explorer2)} />
</div>
)
}
// folder-explorer.module
@Module("FolderExplorer")
export class FolderExplorerModule extends EffectModule<FolderExplorerState> {
defaultState: { [index: string]: FolderExplorerState }= {};
constructor(
private readonly appService: AppService,
private readonly appModule: AppModule,
private readonly authModule: AuthModule,
// ...
) {
super();
}
}
// multi-folder-explorer.module
@Module("MultiFolderExplorer")
export class MultiFolderExplorerModule extends EffectModule<MultiFolderExplorerState> {
defaultState: MultiFolderExplorerState= {
actived: 'explorer1',
// ...
};
constructor(
private readonly appService: AppService,
private readonly appModule: AppModule,
private readonly authModule: AuthModule,
// ...
) {
super();
}
} |
我知道这样可以解决, 但是这样的话 FolderExplorerModule 的 |
是的, 这个是 Sigi 在设计的时候做的取舍。我们用 Class 形式只是因为 DI,但是 Class 会带来额外的组合问题,比如你这个场景其实是 state 树上的多个叶子与同一组 reducer/effect 组合的问题。以前传统的 redux 做法中,reducer/effect 全是纯函数,所以比较好组合。但是 Class 里面就不太容易做这个事情。 但本质上代码量并没有增多,因为无论是 redux 还是 vuex,这种形状 |
请问大致方案会是什么呢, 我现在用的是注册动态 vuex 模块. 订阅 |
以及能和vue devtools的vuex模块打通吗?
The text was updated successfully, but these errors were encountered: