CycleJs - 订阅具有不同 类 的同一元素的事件
CycleJs - Subscribing events of the same element which has different classes
我用 class foo 创建了一个元素。然后我打算在发生点击事件后将其 class 与 bar 交换。但是,当我点击该元素时,订阅 foo 和 bar 点击事件的流被连续触发。结果,元素的 class 没有改变。
如何订阅同一元素的 classes 随时间变化的事件?
这是link:
https://jsbin.com/kanomonexa/edit?html,js,console,output
示例代码如下:
const {div, button, makeDOMDriver} = CycleDOM;
const toggleDriver = (data$)=> {
data$.subscribe(function(data) {
if (data.operation === 'remove' ) {
$(data.selector).removeClass(data.className);
}
else if (data.operation === 'add') {
$(data.selector).addClass(data.className);
}
else {
$(data.selector).toggle(data.className);
}
});
return Rx.Observable.empty();
};
const consoleLogDriver = (data$)=>{
data$.subscribe(data=> {
console.log(data);
});
return Rx.Observable.empty();
};
const main = (sources) =>{
const fooClick$ = sources.DOM
.select('.foo')
.events('click');
const fooLog$ = fooClick$.map(_ =>'.foo is Clicked');
const toggleFoo$ = fooClick$.flatMap(_ => {
const result = [
{
operation: 'remove',
selector: 'button',
className: 'foo'
},
{
operation: 'add',
selector: 'button',
className: 'bar'
}
];
return Rx.Observable.fromArray(result);
});
const barClick$ = sources.DOM
.select('.bar')
.events('click');
const barLog$ = barClick$.map(_ => '.bar is Clicked');
const toggleBar$ = barClick$.flatMap(_ =>{
const result = [
{
operation: 'remove',
selector: 'button',
className: 'bar'
},
{
operation: 'add',
selector: 'button',
className: 'foo'
}
];
return Rx.Observable.fromArray(result);
});
const log$ = Rx.Observable.merge(
fooLog$,
barLog$
);
const toggle$ = Rx.Observable.merge(
toggleFoo$,
toggleBar$
);
const vTree$ = Rx.Observable.of(div([
button('#button.foo',['Click me'])
]));
return {
DOM: vTree$,
consoleLogDriver: log$,
toggleDriver:toggle$
};
};
var drivers = {
DOM: makeDOMDriver('#app'),
toggleDriver: toggleDriver,
consoleLogDriver: consoleLogDriver
};
Cycle.run(main, drivers);
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script>
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<script src="https://rawgit.com/cyclejs/cycle-core/v6.0.3/dist/cycle.js"></script>
<script src="https://rawgit.com/cyclejs/cycle-dom/v9.4.0/dist/cycle-dom.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
您可以 delay(0)
您的 toggle$ 流将其值安排到下一个事件循环,然后成功更改您的 class姓名:
...
const toggle$ = Observable.merge(...)
.delay(0)
...
我看到您正在使用 Jquery 切换 class。根据你想做什么,我想它可以有一些有用的案例(例如:在页面中的其他地方切换一个 dom 范围之外的虚拟 dom)。
但是你的循环应用程序是由虚拟处理的 dom 所以我建议你使用正确的工具来完成这项工作,而不是在每次更改时重建你的 vtree$:
...
const currentClassName$ = Rx.Observable
.merge(
fooClick$.map(_ => '.bar'),
barClick$.map(_ => '.foo')
)
.delay(0) // fix the bug
.startWith('.foo');
const vTree$ = currentClassName$
.map(currentClassName =>
div([
button(
'#button' + currentClassName, ['Click me']
)
]));
...
我用 class foo 创建了一个元素。然后我打算在发生点击事件后将其 class 与 bar 交换。但是,当我点击该元素时,订阅 foo 和 bar 点击事件的流被连续触发。结果,元素的 class 没有改变。 如何订阅同一元素的 classes 随时间变化的事件?
这是link:
https://jsbin.com/kanomonexa/edit?html,js,console,output
示例代码如下:
const {div, button, makeDOMDriver} = CycleDOM;
const toggleDriver = (data$)=> {
data$.subscribe(function(data) {
if (data.operation === 'remove' ) {
$(data.selector).removeClass(data.className);
}
else if (data.operation === 'add') {
$(data.selector).addClass(data.className);
}
else {
$(data.selector).toggle(data.className);
}
});
return Rx.Observable.empty();
};
const consoleLogDriver = (data$)=>{
data$.subscribe(data=> {
console.log(data);
});
return Rx.Observable.empty();
};
const main = (sources) =>{
const fooClick$ = sources.DOM
.select('.foo')
.events('click');
const fooLog$ = fooClick$.map(_ =>'.foo is Clicked');
const toggleFoo$ = fooClick$.flatMap(_ => {
const result = [
{
operation: 'remove',
selector: 'button',
className: 'foo'
},
{
operation: 'add',
selector: 'button',
className: 'bar'
}
];
return Rx.Observable.fromArray(result);
});
const barClick$ = sources.DOM
.select('.bar')
.events('click');
const barLog$ = barClick$.map(_ => '.bar is Clicked');
const toggleBar$ = barClick$.flatMap(_ =>{
const result = [
{
operation: 'remove',
selector: 'button',
className: 'bar'
},
{
operation: 'add',
selector: 'button',
className: 'foo'
}
];
return Rx.Observable.fromArray(result);
});
const log$ = Rx.Observable.merge(
fooLog$,
barLog$
);
const toggle$ = Rx.Observable.merge(
toggleFoo$,
toggleBar$
);
const vTree$ = Rx.Observable.of(div([
button('#button.foo',['Click me'])
]));
return {
DOM: vTree$,
consoleLogDriver: log$,
toggleDriver:toggle$
};
};
var drivers = {
DOM: makeDOMDriver('#app'),
toggleDriver: toggleDriver,
consoleLogDriver: consoleLogDriver
};
Cycle.run(main, drivers);
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script>
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<script src="https://rawgit.com/cyclejs/cycle-core/v6.0.3/dist/cycle.js"></script>
<script src="https://rawgit.com/cyclejs/cycle-dom/v9.4.0/dist/cycle-dom.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
您可以 delay(0)
您的 toggle$ 流将其值安排到下一个事件循环,然后成功更改您的 class姓名:
...
const toggle$ = Observable.merge(...)
.delay(0)
...
我看到您正在使用 Jquery 切换 class。根据你想做什么,我想它可以有一些有用的案例(例如:在页面中的其他地方切换一个 dom 范围之外的虚拟 dom)。
但是你的循环应用程序是由虚拟处理的 dom 所以我建议你使用正确的工具来完成这项工作,而不是在每次更改时重建你的 vtree$:
...
const currentClassName$ = Rx.Observable
.merge(
fooClick$.map(_ => '.bar'),
barClick$.map(_ => '.foo')
)
.delay(0) // fix the bug
.startWith('.foo');
const vTree$ = currentClassName$
.map(currentClassName =>
div([
button(
'#button' + currentClassName, ['Click me']
)
]));
...