如何使用 Cycle.js 创建一个动态的、重复的元素列表?
How do I create a dynamic, repeating list of elements with Cycle.js?
使用 Cycle.js,我试图创建一个视图,在给定一组数据点时呈现动态数量的组件。但是,我不知道如何创建重复视图。
我已将所有内容剥离回我认为它应该如何工作的最基本示例。希望有人能指出我所缺少的。
/*
Expected:
Given an array of data objects, create the following DOM
<div class="container">
<h1 class=".data">Element 1</h1>
<h1 class=".data">Element 2</h1>
<h1 class=".data">Element 3</h1>
<h1 class=".data">Element 4</h1>
...
</div>
Result:
<div class="container">
<h1 class=".data">Element 9</h1>
</div>
*/
function view( data$ ){
return Rx.Observable.of(
div('.container', data$.map( data =>
h1('.data', `Element: ${ data.id }`)
))
);
}
function main( sources ) {
// Create an array of objects
const arr = [];
for( let i = 0; i < 10; i++ ){
arr.push({
id: `id ${i}`
})
}
// Convert array to an observable
const data$ = Rx.Observable.from(arr);
const vtree$ = view( data$ );
return {
DOM: vtree$
};
}
const drivers = {
DOM: CycleDOM.makeDOMDriver('#mountPoint')
};
Cycle.run( main, drivers );
您的数组有 10 个项目,因此 observable 将发出 10 个项目。 Observables 表示随时间变化的数据。所以你的 observable 代表 10 个时间点。其中只有最近的将被使用。这就是为什么您只看到 "element 9".
与其将数组转换为可观察对象,不如创建一个仅包含一项的可观察对象:数组。
把Rx.Observable.from(arr)
改成Rx.Observable.just(arr)
下一期是你的视图函数:
function view( data$ ){
return Rx.Observable.of(
div('.container', data$.map( data =>
h1('.data', `Element: ${ data.id }`)
))
);
}
您的视图函数采用 data$
参数。将 data$
读作 data stream
或 stream of data
。所以你的函数接受一个流
到目前为止是正确的。
但是现在您正在通过 Observable.of
创建一个新的 Observable。那不是你想做的。相反,您可能只想将 data$
- 即数据流 - 转换为虚拟 DOM 节点流:
function view( data$ ){
return data$.map( data =>
// here you should return a virtual DOM node
)
}
记住:data$
是您一段时间内的数据。对于每个时间点,您都有一些数据。对于每个时间点,您都希望拥有一些 DOM 树。
function view( data$ ){
return data$.map( data =>
div('.container',
// data is not a single of your items but the whole array of items
// hence we can map over it and transform each item into a child nod:
data.map((item) => div('.item', item.id))
)
)
}
注意:data$.map
与 data.map 有很大不同。第一个 transforms/maps 一个可观察的,后面的 transforms/maps 一个经典数组。
奖金:
for( let i = 0; i < 10; i++ ){
arr.push({
id: `id ${i}`
})
}
您正在以程序方式创建数组。您可能更喜欢创建大小为 10 的数组并将其转换为包含项目的数组的函数式方法:
Array.apply(Array, {length: 10}).map(
(_,index) => ({id: `id: ${index}`})
)
Cycle 有一个 Collection 模块。它采用对象数组流并将它们隔离。我使用 npm 获取这些模块并使用 webpack 进行部署。
import Cycle from '@cycle/xstream-run';
import Collection from '@cycle/collection';
import {div,h1} from '@cycle/dom';
import { makeDOMDriver } from '@cycle/dom';
import xs from 'xstream';
function view( comb$ ){
return comb$.debug('view').map( tup =>{
const item = tup[0];
const clicked = tup[1];
return div('.container', [ h1( '.data', `Element: ${item.id} clicked: ${clicked}`)]);
});
}
/* Item Component */
function Item ( sources ){
const intent$ = sources.DOM //Events on DOM are limited to only ones on sink DOM
.select('div')
.events('click').mapTo('yes').startWith('no').debug('item clicks');
return {
DOM: view( xs.combine( sources.itemJaJa, intent$) )
};
}
function main(sources) {
const arr = [];
for( let i = 0; i < 10; i++ ){
arr.push(
//The way Collection add the obj to the source is odd
//this is what's worked for me
{ id_to_collection: i, //identifier used by collection
itemJaJa:{
id: `id ${i}`
}
} );
}
const items = Collection.gather(Item, sources, xs.of( arr),'id_to_collection' );
const vtrees$ = Collection.pluck( items, item=>item.DOM);
return {
DOM: vtrees$.map( itemDomList => div('.top',itemDomList)),
};
}
const drivers ={
DOM: makeDOMDriver('#app')
};
Cycle.run(main, drivers);
使用 Cycle.js,我试图创建一个视图,在给定一组数据点时呈现动态数量的组件。但是,我不知道如何创建重复视图。
我已将所有内容剥离回我认为它应该如何工作的最基本示例。希望有人能指出我所缺少的。
/*
Expected:
Given an array of data objects, create the following DOM
<div class="container">
<h1 class=".data">Element 1</h1>
<h1 class=".data">Element 2</h1>
<h1 class=".data">Element 3</h1>
<h1 class=".data">Element 4</h1>
...
</div>
Result:
<div class="container">
<h1 class=".data">Element 9</h1>
</div>
*/
function view( data$ ){
return Rx.Observable.of(
div('.container', data$.map( data =>
h1('.data', `Element: ${ data.id }`)
))
);
}
function main( sources ) {
// Create an array of objects
const arr = [];
for( let i = 0; i < 10; i++ ){
arr.push({
id: `id ${i}`
})
}
// Convert array to an observable
const data$ = Rx.Observable.from(arr);
const vtree$ = view( data$ );
return {
DOM: vtree$
};
}
const drivers = {
DOM: CycleDOM.makeDOMDriver('#mountPoint')
};
Cycle.run( main, drivers );
您的数组有 10 个项目,因此 observable 将发出 10 个项目。 Observables 表示随时间变化的数据。所以你的 observable 代表 10 个时间点。其中只有最近的将被使用。这就是为什么您只看到 "element 9".
与其将数组转换为可观察对象,不如创建一个仅包含一项的可观察对象:数组。
把Rx.Observable.from(arr)
改成Rx.Observable.just(arr)
下一期是你的视图函数:
function view( data$ ){
return Rx.Observable.of(
div('.container', data$.map( data =>
h1('.data', `Element: ${ data.id }`)
))
);
}
您的视图函数采用 data$
参数。将 data$
读作 data stream
或 stream of data
。所以你的函数接受一个流
到目前为止是正确的。
但是现在您正在通过 Observable.of
创建一个新的 Observable。那不是你想做的。相反,您可能只想将 data$
- 即数据流 - 转换为虚拟 DOM 节点流:
function view( data$ ){
return data$.map( data =>
// here you should return a virtual DOM node
)
}
记住:data$
是您一段时间内的数据。对于每个时间点,您都有一些数据。对于每个时间点,您都希望拥有一些 DOM 树。
function view( data$ ){
return data$.map( data =>
div('.container',
// data is not a single of your items but the whole array of items
// hence we can map over it and transform each item into a child nod:
data.map((item) => div('.item', item.id))
)
)
}
注意:data$.map
与 data.map 有很大不同。第一个 transforms/maps 一个可观察的,后面的 transforms/maps 一个经典数组。
奖金:
for( let i = 0; i < 10; i++ ){
arr.push({
id: `id ${i}`
})
}
您正在以程序方式创建数组。您可能更喜欢创建大小为 10 的数组并将其转换为包含项目的数组的函数式方法:
Array.apply(Array, {length: 10}).map(
(_,index) => ({id: `id: ${index}`})
)
Cycle 有一个 Collection 模块。它采用对象数组流并将它们隔离。我使用 npm 获取这些模块并使用 webpack 进行部署。
import Cycle from '@cycle/xstream-run';
import Collection from '@cycle/collection';
import {div,h1} from '@cycle/dom';
import { makeDOMDriver } from '@cycle/dom';
import xs from 'xstream';
function view( comb$ ){
return comb$.debug('view').map( tup =>{
const item = tup[0];
const clicked = tup[1];
return div('.container', [ h1( '.data', `Element: ${item.id} clicked: ${clicked}`)]);
});
}
/* Item Component */
function Item ( sources ){
const intent$ = sources.DOM //Events on DOM are limited to only ones on sink DOM
.select('div')
.events('click').mapTo('yes').startWith('no').debug('item clicks');
return {
DOM: view( xs.combine( sources.itemJaJa, intent$) )
};
}
function main(sources) {
const arr = [];
for( let i = 0; i < 10; i++ ){
arr.push(
//The way Collection add the obj to the source is odd
//this is what's worked for me
{ id_to_collection: i, //identifier used by collection
itemJaJa:{
id: `id ${i}`
}
} );
}
const items = Collection.gather(Item, sources, xs.of( arr),'id_to_collection' );
const vtrees$ = Collection.pluck( items, item=>item.DOM);
return {
DOM: vtrees$.map( itemDomList => div('.top',itemDomList)),
};
}
const drivers ={
DOM: makeDOMDriver('#app')
};
Cycle.run(main, drivers);