gpt4 book ai didi

javascript - Cyclejs 应该为 Elm/Redux 等 Action 建模吗?

转载 作者:行者123 更新时间:2023-12-01 02:23:46 25 4
gpt4 key购买 nike

我正在玩cyclejs,我试图找出处理许多源/意图的惯用方法应该是什么。我在下面有一个简单的 Cyclejs 程序,用 TypeScript 编写,并对最相关的部分进行了注释。

您是否应该像在 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')
});

最佳答案

在我看来,您不应该像您那样多路复用意图流(将所有意图合并到单个流中)。

相反,您可以尝试在 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 函数中的化简器,合并这些化简器,最后折叠它们

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);
}

该解决方案的多个优点:

  • 您可以输入函数的参数并检查是否传递了正确的流;
  • 如果操作数量增加,您不需要巨大的开关
  • 您不需要操作标识符。

在我看来,当两个组件之间存在父/子关系时,多路复用/多路解复用流是很好的。这样,父级只能使用它需要的事件(这更多的是一种直觉,而不是一般规则,它需要更多的思考:))

关于javascript - Cyclejs 应该为 Elm/Redux 等 Action 建模吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48983189/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com