By
    
      被删
    
  
    
    更新日期:
    
  
	
		
		
		
		
		因为对Rxjs的好感玩上了Cycle.js,《Cycle.js学习笔记》系列用于记录使用该框架的一些笔记。
本文我们从了解Driver驱动开始,完成Input值的设置set value,然后实现Input的双向绑定。
有小伙伴们把Cycle.js翻译中文了,大家可以看看中文文档。
Driver驱动
这里我们先来看看什么是Driver。
Driver其实是一些函数,它用来监听输入流,然后执行必要的副作用操作,最后可能会返回输出流。
至于抽象想象什么的,本骚年已经在《Cycle.js学习笔记5–关于框架设计和抽象》中发挥过脑洞的力量了。
Driver应该始终与某些I/O effect联系在一起。
大多数Driver,比如DOM Driver,以sink(为了描述write)作为输入,以source(为了捕获read)作为输出。
像我们要实现一个Websocket的Driver:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
   | import {adapt} from '@cycle/run/lib/adapt';
  function makeSockDriver(peerId) {   let sock = new Sock(peerId);
    function sockDriver(outgoing$) {          outgoing$.addListener({       next: outgoing => {         sock.send(outgoing));       },       error: () => {},       complete: () => {},     });
           const incoming$ = xs.create({       start: listener => {         sock.onReceive(function (msg) {           listener.next(msg);         });       },       stop: () => {},     });
      return adapt(incoming$);   }
    return sockDriver; }
  | 
 
实现流创建和监听
我们希望能通过set value的方式注入流,我们可以创建一个流,然后调用监听器:
- 创建流,提取出监听器。
 
- 将1步骤创建的流作为输入更新Input的value。
 
- 在调用
setValue()方法时触发监听器。 
- 将Input的
change或者keyup事件流,合并3步骤更新的流,作为输出。 
我们大概能得到这样一个Input:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
   | @bindMethods export class InputComponent {   id;   listener;   DOM;   inputGet;   inputSet;   constructor(domSource, type) {     this.id = id++;
           this.inputSet = xs.create({       start: listener => {         this.listener = listener;       },       stop: () => {},     }).startWith(undefined);
           this.DOM = xs.merge(this.inputSet).map(val =>       <input type={type} id={'input' + this.id} className="form-control" value={val} />     );
           this.inputGet = xs.merge(domSource.select('#input' + this.id).events('keyup')     .map(ev => ev.target.value), this.inputSet).startWith('');   }   getDOM() {     return this.DOM;   }   getValue() {     return this.inputGet;   }   setValue(val) {          this.listener.next(val);   } }
   | 
 
检验实现
检验的时候到了,我们通过设置一个定时器,触发Input输入的自动更新,当然,你也可以自己手动输入验证。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
   | export function LoginComponent(sources) {     const domSource = sources.DOM;
           const loginClick$ = domSource.select('#submit').events('click')
           const unameInputSource = new InputComponent(domSource, 'text')     const unameInputDOM$ = unameInputSource.getDOM()     const unameInputValue$ = unameInputSource.getValue()
           let a = 1;     setInterval(() => {         unameInputSource.setValue(a++);     }, 1000);
           const loginView$ = xs.combine(unameInputDOM$, unameInputValue$).map(([unameDOM, unameValue]) => {         return (             <form>                 <h1>System</h1>                 <div>                     {unameDOM}                 </div>                 {unameValue}                 <div>                     <a className="btn btn-default" id="submit">Login</a>                 </div>             </form>         )     }     );     return {         DOM: loginView$,         router: loginClick$.mapTo("/app")     }; }
  | 
 
双向绑定
我们能看到,在定时器的作用下,Input值每秒自增,同时获取到的值也触发更新。
当我们讲输入和输出连接到一起的时候,我们就实现了简单的双向绑定。前面也说过了,双向绑定只是个语法糖而已,拆开来说也就是能设置输入,并获取输出。
这时候,我们巧妙地使用get和set,就可以实现双向绑定:
1 2 3 4 5 6 7 8 9 10 11 12
   | @bindMethods export class InputComponent {         get value() {     return this.inputGet;   }   set value(val) {          this.listener.next(val);   } }
   | 
 
这样,我们在使用的时候:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | export function LoginComponent(sources) {   
       const unameInputSource = new InputComponent(domSource, 'text')   const unameInputDOM$ = unameInputSource.getDOM()      const unameInputValue$ = unameInputSource.value
       let a = 1;   setInterval(() => {          unameInputSource.value = a++;   }, 1000); }
  | 
 
塔嗒!是不是好了。
结束语
这节主要简单(真的很简单)介绍了驱动Driver,并成功地完成了之前没有完成的部分,完成Input的输入,并将Input的输入和输出衔接在一起,对外呈现出一种双向绑定的方式。
此处查看项目代码
此处查看页面效果
  
	 
	
		
			查看Github有更多内容噢:https://github.com/godbasin
			
			更欢迎来被删的前端游乐场边撸猫边学前端噢
			
			
			如果你想要关注日常生活中的我,欢迎关注“牧羊的猪”公众号噢