2016-04-21 47 views
0

我创建了一个类别为foo的元素。然后,我打算在点击事件发生后将其课程与酒吧交换。然而,当我点击元素时,连续触发了订阅foo的点击事件的流。结果,元素的类没有改变。 我怎样才能订阅相同元素的事件,其类别随时间变化?CycleJs - 具有不同类别的相同元素的订阅事件

这里的链接:

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>

回答

1

您可能delay(0)你拨动$流安排其值到下一个事件循环,然后成功更改您的className:

... 
const toggle$ = Observable.merge(...) 
    .delay(0) 
... 

我看到你使用jQuery来切换类。根据你想要做什么,我想它可以有一些有用的情况下(例如:在虚拟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'] 
    ) 
    ])); 
... 

Working demo

+0

感谢正确答案。我不明白的是为什么我必须使用delay(0)。我的意思是有一个点击事件,当它发生时,元素具有foo类。其中规定了酒吧的点击事件的流程如何呢?你能解释一下使用延迟如何解决这个问题吗?关于使用toggleDriver,我认为你是对的。最好使用v-dom而不是$。我创建了切换驱动程序,因为我认为更改元素类是一种副作用,在驱动程序中执行操作比在虚拟目录中使用相同的代码更容易。谢谢再次帮助 – erdal

+1

很高兴为您提供帮助。然而,我很抱歉,但我无法解释。我只能猜测这可能是事件由dom驱动程序处理的一个问题:所有事件都会冒泡到根元素并形成一个流。然后执行.select返回按目标过滤的此流的副本。直觉上我认为让dom重新渲染(延迟(0))可能会有所帮助。我认为在GitHub上报告它可能是个好问题。 (写在我的手机上) – Fuunnx

+0

关于改变classNames,你是对的,这是一个副作用。但是,当您更改虚拟树时,它已由domDriver处理。在时间_x_上将vTree视为您的应用程序的图形表示。 – Fuunnx

相关问题