【问题标题】:CycleJs - Subscribing events of the same element which has different classesCycleJs - 订阅具有不同类的同一元素的事件
【发布时间】:2016-08-14 02:50:19
【问题描述】:

我用 foo 类创建了一个元素。然后我打算在发生点击事件后将其类与 bar 交换。然而,当我点击元素时,订阅了 foobar 的点击事件的流被相继触发。结果,元素的类没有改变。 如何订阅其类随时间变化的同一元素的事件?

这是链接:

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>

【问题讨论】:

    标签: cyclejs virtual-dom


    【解决方案1】:

    您可以delay(0)您的 toggle$ 流将其值安排到下一个事件循环,然后成功更改您的 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)。我的意思是有一个点击事件,当它发生时,元素有 foo 类。订阅 bar 的点击事件的流如何工作?您能否解释一下使用延迟如何解决问题?关于使用toggleDriver,我认为你是对的。最好使用 v-dom 而不是 $。我创建了切换驱动程序,因为我认为更改元素类是一种副作用,并且在驱动程序中执行此操作比在我使用 virtual-dom 的任何地方编写相同的代码更容易。再次感谢您的帮助
    • 很高兴为您提供帮助。但是我很抱歉,但我无法解释。我只能猜测这可能是 dom 驱动程序处理事件的方式存在问题:所有事件都冒泡到根元素并形成一个流。然后执行 .select 返回按目标过滤的此流的副本。直觉上我认为让dom重新渲染(延迟(0))可能会有所帮助。我认为在 GitHub 上将其报告为问题可能会很好。 (写在我的手机上)
    • 关于改变classNames,你是对的,这是一个副作用。但是当您更改虚拟树时,它已经由 domDriver 处理。将 vTree 视为您的应用在时间 x 时的图形表示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-04
    • 2019-08-05
    • 1970-01-01
    • 2019-12-08
    相关资源
    最近更新 更多