我正在尝试cyclejs,我正在尝试找出处理许多来源/意图的惯用方式应该是什么。我在下面的TypeScript中有一个简单的cyclejs程序,对最相关的部分进行了注释。
您是否应该像在Elm或Redux中那样将源/意图建模为谨慎的事件,或者您是否应该在流操作方面做一些更聪明的事情?当应用程序很大时,我很难理解如何避免这种事件模式。
如果这是正确的方式,它不会最终成为增加了流管理复杂性的Elm的JS版本吗?
import { div, DOMSource, h1, makeDOMDriver, VNode, input } from '@cycle/dom';
import { run } from '@cycle/xstream-run';
import xs, { Stream } from 'xstream';
import SearchBox, { SearchBoxProps } from './SearchBox';
export interface Sources {
DOM: DOMSource;
}
export interface Sinks {
DOM: Stream<VNode>
}
interface Model {
search: string
searchPending: {
[s: string]: boolean
}
}
interface SearchForUser {
type: 'SearchForUser'
}
interface SearchBoxUpdated {
type: 'SearchBoxUpdated',
value: string
}
type Actions = SearchForUser | SearchBoxUpdated;
/**
* Should I be mapping these into discreet events like this?
*/
function intent(domSource: DOMSource): Stream<Actions> {
return xs.merge(
domSource.select('.search-box')
.events('input')
.map((event: Event) => ({
type: 'SearchBoxUpdated',
value: ((event.target as any).value as string)
} as SearchBoxUpdated)),
domSource.select('.search-box')
.events('keypress')
.map(event => event.keyCode === 13)
.filter(result => result === true)
.map(e => ({ type: 'SearchForUser' } as SearchForUser))
)
}
function model(action$: Stream<Actions>): Stream<Model> {
const initialModel: Model = {
search: '',
searchPending: {}
};
/*
* Should I be attempting to handle events like this?
*/
return action$.fold((model, action) => {
switch (action.type) {
case 'SearchForUser':
return model;
case 'SearchBoxUpdated':
return Object.assign({}, model, { search: action.value })
}
}, initialModel)
}
function view(model$: Stream<Model>): Stream<VNode> {
return model$.map(model => {
return div([
h1('Github user search'),
input('.search-box', { value: model.search })
])
})
}
function main(sources: Sources): Sinks {
const action$ = intent(sources.DOM);
const state$ = model(action$);
return {
DOM: view(state$)
};
}
run(main, {
DOM: makeDOMDriver('#main-container')
});发布于 2018-02-27 17:32:35
在我看来,您不应该像您那样多路复用意图流(将所有意图合并到单个流中)。
相反,您可以尝试在intent函数中返回多个流。
类似于:
function intent(domSource: DOMSource): SearchBoxIntents {
const input = domSource.select("...");
const updateSearchBox$: Stream<string> = input
.events("input")
.map(/*...*/)
const searchForUser$: Stream<boolean> = input
.events("keypress")
.filter(isEnterKey)
.mapTo(true)
return { updateSearchBox$, searchForUser$ };
}然后,您可以将这些操作映射到model函数中的缩减程序,合并这些缩减程序,最后对它们执行fold操作
function model({ updateSearchBox$, searchForUser$ }: SearchBoxIntents): Stream<Model> {
const updateSearchBoxReducer$ = updateSearchBox$
.map((value: string) => model => ({ ...model, search: value }))
// v for the moment this stream doesn't update the model, so you can ignore it
const searchForUserReducer$ = searchForUser$
.mapTo(model => model);
return xs.merge(updateSearchBoxReducer$, searchForUserReducer$)
.fold((model, reducer) => reducer(model), initialModel);
}此解决方案具有多项优势:
你可以输入你的函数的参数,并检查是否传递了正确的流;如果动作的数量increases;
,你就不需要很大的
switch在我看来,当两个组件之间存在父/子关系时,多路复用/多路分解流是很好的。这样,父级只能使用它需要的events (这更像是一种直觉,而不是一般规则,它需要更多的思考:)
https://stackoverflow.com/questions/48983189
复制相似问题