gpt4 book ai didi

javascript - 如何使用 RxJS 在 Cyclejs 中将 Observable 流转换为单独的可更新 div

转载 作者:行者123 更新时间:2023-11-30 16:24:05 24 4
gpt4 key购买 nike

我正在尝试获取一个包含 10 个对象的随机 Observable 流,每个对象都具有如下属性:

{tileNum: '6', tileName: 'game-of-thrones' clickCount:'1'}

接下来,每当对象内部相同的 tileNum 使用 tileNum 通过流时,clickCount 就需要增加。现在对于棘手的一点,流式传输每个 tileNum 需要附加到一个 div (0-9),这些 div 需要预先填充并且 clickCount 增加附加到对象的相关 div。例如:

div 6 = clickCount:'1' => {tileNum: '6'..} => div 6 = clickCount:'2'

到目前为止我有:

const tile = (sources) => {
const incomingMessages$ = sources.socketIO.get('newClickStream'); // continuous Observable
const state$ = model(incomingMessages$);
const view$ = view(state$);
return {
DOM: view$,
}
};

index.js

const model = actions =>
actions.groupBy((tile) => tile.tileNum)
.flatMap(
(tile$) =>
tile$
.scan((prev, {tileName, tileNum}, index) => ({
tileNum,
tileName,
clickCount: index + 1
}))
.do(x => console.log(x))
);
export default model;

model.js

const view = (state$) =>
state$.map(source => {
return div([
h(`div#${source.tileNum}`, {}, ['${source.clickCount}']),
])
});
export default view;

view.js

现在我只能填充一个随每个新流对象而变化的 div。作为警告但不是必需的,如果 div 可以按 clickCount 排序,那将是惊人的。

最佳答案

我稍微简化了代码并插入了解释作为注释。

const Cycle = require('@cycle/core');
const {makeDOMDriver, div} = require('@cycle/dom');
const {Observable} = require('rx');

const model = (tiles, actions) =>
// since we already know all the tiles we just a a stream with one item which represents all the current tiles.
Observable.just(
// we map the array of tiles into an array of streams
tiles.map(
(t) => {
return actions.incomingMessages$
// As each of those streams belongs to one specific tile we filter
// the click events to match this tile
.filter((click) => {
return click.tileNum === t
})
// We start with a click count of 0
.startWith({
tileNum: t,
count: 0
})
// for each click we increse the click count by 1
.scan(({tileNum, count}) => ({
tileNum,
count: count+1,
}))
}
))
;

const view = (state$) =>
// The view is a mapping from the current stream to a vnode tree
// the state contains the list of all tiles as array
// This is a stream mapping
state$.map((tiles) => div(
// the list of tiles is a plain array
// we map each tile into a vnode
// this is a plain array mapping
tiles.map((tile) =>
// Each tile itself is a stream of click counts
// We are only interessted in the latest click count
// We map this stream into vnodes
tile.map((t) =>
// t is the the object containing the tiles id and the current click count
// We just create a vnode populated with this data.
div('.tile', {
attributes: {'data-tile-num': t.tileNum}
},t.tileNum+': '+t.count))
)
)
);

const main = (sources) => {
// I replaced your incoming messages with a stream I get from click events.
const incomingMessages$ = sources.DOM
.select('.tile').events('click')
.map((evt) => ({tileNum: parseInt(evt.target.dataset.tileNum, 10)}));

// You already know all the tiles which exist.
// You do not only want to show clicked tiles but even tiles which have never been clicked.
// That's why instead of collection the tiles itself from a stream via groubBy
// which can just create an array with all the tiles.
const tiles = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,77,18,19];
const state$ = model(tiles, {incomingMessages$});
const view$ = view(state$);
return {
DOM: view$,
}
};

const sources = {
DOM: makeDOMDriver('.app')
}

Cycle.run(main, sources);

You can paste the code here to run it in your browser

关于javascript - 如何使用 RxJS 在 Cyclejs 中将 Observable 流转换为单独的可更新 div,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34364909/

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