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);
    
      
  • 相关阅读:
    微信小程序如何获取openid
    js经典试题之常用的方法
    js经典试题之运算符的优先级
    js如何使浏览器允许脚本异步加载
    es6从零学习(五):Module的语法
    es6从零学习(四):Class的继承
    js如何处理字符串中带有↵字符
    Zuul中聚合Swagger的坑
    阿里Sentinel支持Spring Cloud Gateway啦
    Spring Boot中的Mongodb多数据源扩展
  • 原文地址:https://www.cnblogs.com/Answer1215/p/5178725.html
Copyright © 2011-2022 走看看