zoukankan      html  css  js  c++  java
  • [Cycle.js] Read effects from the DOM: click events

    So far we only had effects that write something to the external world, we are not yet reading anything from the external world into our app. This lesson shows how we can change the DOM Driver to return a "DOM Source" representing read effects, such as click events. We will leverage that to create an interactive application.

    // Logic (functional)
    function main() {
      return {
        DOM: Rx.Observable.timer(0, 1000)
          .map(i => `Seconds elapsed ${i}`),
        Log: Rx.Observable.timer(0, 2000).map(i => 2*i),
      };
    }
    
    // Effects (imperative)
    function DOMEffect(text$) {
      text$.subscribe(text => {
        const container = document.querySelector('#app');
        container.textContent = text;
      });
    }
    
    function consoleLogEffect(msg$) {
      msg$.subscribe(msg => console.log(msg));
    }
    
    const effects = {
        DOM: DOMEffect,
        Log: consoleLogEffect
    }
    
    function run(mainFn, effects){
      const sinks = mainFn();
      Object.keys(effects)
        .forEach( (effectKey)=>{
        effects[effectKey](sinks[effectKey]);
      })
    }
    
    run(main, effects);

    Source: stands for input, read effect

    sink: stands for output, write effect

    So main() function need to take a param 'DOMSource' and effects function need return value:

    function main(DOMSource) {
       ...   
    }
    
    function DOMDriver() {
      ...
      const DOMSource = Rx.Observable.fromEvent(document, 'clicik');
      return DOMSource;  
    }
    
    function run(mainFn, drivers) {
       const sinks = mainFn(DOMSource);
       const DOMSource = drivers['DOM'](sinks['DOM'])
       ....
    }

    The problem in the code above is that:

      the main function need param 'DOMSource' which is returned by the driver DOMDriver. But for create DOMSource in run() function, we need pass DOMSource to the main() function. So 'DOMSource' is actually used before it created.

    I can simply the problem as:

    a = f(b); // we need b to create a

    b = g(a) // we need a to create b

    So there is a cycle going on between main() function and driver() function.

    The solution to sovle this problem is :

     A is an observable and also B is an observable. If we actually instead of using B, we could use something like B proxy here. Because B proxy is now available for f() as an argument.

    Then that helps us to make A, and then given A we can make B. Then now that we have B, we can feed back all of the events that happen on B into B proxy. So that's what we're going to try to achieve.

    bProxy = ...

    a = f(bProxy)

    b = g(a)

    bProxy.imitat(b)

    So the code looks like:

    // Logic (functional)
    function main(DOMSource) {
      const click$ = DOMSource;
      return {
        DOM: click$
          .startWith(null)
          .flatMapLatest(() => 
            Rx.Observable.timer(0, 1000)
             .map(i => `Seconds elapsed ${i}`)           
          ),
        Log: Rx.Observable.timer(0, 2000).map(i => 2*i),
      };
    }
    
    // source: input (read) effects
    // sink: output (write) effects
    
    // Effects (imperative)
    function DOMDriver(text$) {
      text$.subscribe(text => {
        const container = document.querySelector('#app');
        container.textContent = text;
      });
      const DOMSource = Rx.Observable.fromEvent(document, 'click');
      return DOMSource;
    }
    
    function consoleLogDriver(msg$) {
      msg$.subscribe(msg => console.log(msg));
    }
    
    // bProxy = ...
    // a = f(bProxy)
    // b = g(a)
    // bProxy.imitate(b)
    
    function run(mainFn, drivers) {
      const proxyDOMSource = new Rx.Subject();
      const sinks = mainFn(proxyDOMSource);
      const DOMSource = drivers.DOM(sinks.DOM);
      DOMSource.subscribe(click => proxyDOMSource.onNext(click));
    //   Object.keys(drivers).forEach(key => {
    //     drivers[key](sinks[key]);
    //   });
    }
    
    const drivers = {
      DOM: DOMDriver,
      Log: consoleLogDriver,
    }
    
    run(main, drivers);
    
      
  • 相关阅读:
    “Computer Management Snapin Launcher已停止工作”的解决方案
    IFrame与window对象(contentWindow)
    使用Emeditor转换编码(ShiftJS 到 UTF8)
    从注册表中删除程序,不要忘记这两个地方
    Visual Studio fatal error C1902: 程序数据库管理器不匹配;请检查安装
    一些TC内置的环境环境变量(注意字母必须大写,且只能在TC内用)
    使用WIN32 API CreateProcess()以无窗口方式创建DOS程序
    VC中DDX/DDV自定义
    javascript 一条语句实现随机数语句
    Emeditor
  • 原文地址:https://www.cnblogs.com/Answer1215/p/5178725.html
Copyright © 2011-2022 走看看