[Cycle.js] Read effects from the DOM: click events

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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);

  

 

以上是关于[Cycle.js] Read effects from the DOM: click events的主要内容,如果未能解决你的问题,请参考以下文章

[Cycle,js] Customizing effects from the main function

[Cycle.js] Introducing run() and driver functions

Effective Go(官方文档)笔记

[Cycle.js] Hello World in Cycle.js

学习RxJS:Cycle.js

学习RxJS:Cycle.js