侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

学习RxJS之JavaScript框架Cycle.js

前端  /  管理员 发布于 5年前   370

是什么

Cycle.js 是一个极简的JavaScript框架(核心部分加上注释125行),提供了一种函数式,响应式的人机交互接口(以下简称HCI):

函数式

Cycle.js 把应用程序抽象成一个纯函数 main(),从外部世界读取副作用(sources),然后产生输出(sinks) 传递到外部世界,在那形成副作用。这些外部世界的副作用,做为Cycle.js的插件存在(drivers),它们负责:处理DOM、提供HTTP访问等。

响应式
Cycle.js 使用 rx.js 来实现关注分离,这意味着应用程序是基于事件流的,数据流是Observable 的:

HCI

HCI 是双向的对话,人机互为观察者

在这个交互模型中,人机之间的信息流互为输出输出,构成一个循环,也即 Cycle这一命名所指,框架的Logo更是以莫比乌斯环贴切的描述了这个循环。cycle_log

唯一的疑惑会是:循环无头无尾,信息流从何处发起?好问题,答案是:

However, we need a .startWith() to give a default value. Without this, nothing would be shown! Why? Because our sinks is reacting to sources, but sources is reacting to sinks. If no one triggers the first event, nothing will happen. ―― via examples

有了.startWith() 提供的这个初始值,整个流程得以启动,自此形成一个闭环,一个事件驱动的永动机 :)

Drivers

driver 是 Cycle.js 主函数 main()和外部世界打交道的接口,比如HTTP请求,比如DOM操作,这些是由具体的driver 负责的,它的存在确保了 main()的纯函数特性,所有副作用和繁琐的细节皆由 driver来实施――所以 @cycle/core 才125 行,而@cycle/dom 却有 4052 行之巨。

driver也是一个函数,从流程上来说,driver 监听sinks(main()的输出)做为输入,执行一些命令式的副作用,并产生出sources做为main()的输入。

DOM Driver

即 @cycle/dom,是使用最为频繁的driver。实际应用中,我们的main()会与DOM进行交互:

  • 需要传递内容给用户时,main()会返新的DOM sinks,以触发domDriver()生成virtual-dom,并渲染
  • main()订阅domDriver()的输出值(做为输入),并据此进行响应

组件化
每个Cycle.js应用程序不管多复杂,都遵循一套输入输出的基本法,因此,组件化是很容易实现,无非就是函数对函数的组合调用

实战

准备工作

安装全局模块

依赖模块一览

"devDependencies": {"babel-plugin-transform-react-jsx": "^6.8.0","babel-preset-es2015": "^6.9.0","babelify": "^7.3.0","browserify": "^13.0.1","uglifyify": "^3.0.1","watchify": "^3.7.0"},"dependencies": {"@cycle/core": "^6.0.3","@cycle/dom": "^9.4.0","@cycle/http": "^8.2.2"}

.babelrc (插件支持JSX语法)

{"plugins": [["transform-react-jsx", { "pragma": "hJSX" }]],"presets": ["es2015"]}

Scripts(热生成和运行服务器)

"scripts": {"start": "http-server","build": "../node_modules/.bin/watchify index.js -v -g uglifyify -t babelify -o bundle.js"}

以下实例需要运行时,可以开两个shell,一个跑热编译,一个起http-server(爱用currently亦可

交互实例1

功能:两个button,一加一减, 从0起步,回显计数
demo地址: http://output.jsbin.com/lamexacaku

HTML代码

components

index.js

import Cycle from '@cycle/core'import { makeDOMDriver, hJSX } from '@cycle/dom'function main({ DOM }) {const decrement$ = DOM.select('.decrement').events('click').map(_ => -1)const increment$ = DOM.select('.increment').events('click').map(_ => +1)const count$ = increment$.merge(decrement$).scan((x, y) => x + y).startWith(0)return {DOM: count$.map(count =>Clicked {count} times~)}}Cycle.run(main, {DOM: makeDOMDriver('#container'),})

不难看出:

  • main()是个纯函数,从始至终不依赖外部状态,它的所有动力来自于DOM事件源click,这个状态机依靠Observable.prototype.scan()得以计算和传递,最后生成sinks传递给DOM driver以渲染;
  • 启动了这个循环是 .startWith();
  • Cycle.run是应用程序的入口,加载main()和DOM driver,后者对一个HTML容器进行渲染输出

交互实例2

功能: 一个button一个框,输入并点button后,通过Github api搜索相关的Repo,回显总数并展示第一页Repo列表

index.js

import Cycle from '@cycle/core'import { makeDOMDriver, hJSX } from '@cycle/dom'import { makeHTTPDriver } from '@cycle/http'const GITHUB_SEARCH_URL = 'https://api.github.com/search/repositories?q='function main(responses$) {const search$ = responses$.DOM.select('input[type="button"]').events('click').map(_ => { return { url: GITHUB_SEARCH_URL } })const text$ = responses$.DOM.select('input[type="text"]').events('input').map(e => { return { keyword: e.target.value } })const http$ = search$.withLatestFrom(text$, (search, text)=> search.url + text.keyword).map(state => { return { url: state, method: 'GET' } })const dom$ = responses$.HTTP.filter(res$ => res$.request.url && res$.request.url.startsWith(GITHUB_SEARCH_URL)).mergeAll().map(res => JSON.parse(res.text)).startWith({ loading: true }).map(JSON => {return 
{JSON.loading ? 'Loading...' : `total: ${JSON.total_count}`}
    {JSON.items && JSON.items.map(repo =>repo.full_name{ repo.html_url })}
})return {DOM: dom$,HTTP: http$,}}const driver = {DOM: makeDOMDriver('#container'),HTTP: makeHTTPDriver(),}Cycle.run(main, driver)

有了实例1做铺垫,这段代码也就通俗易懂了,需要提示的是:

  • Rx的Observable对象,命名上约定以$符为结束,以示区分
  • Observable.prototype.withLatestFrom()的作用是:在当前Observable对象的事件触发时(不同于 combineLatest),去合并参数的目标Observable对象的最新状态,并传递给下一级Observer
  • 以上项目完整实例,可在 /rockdragon/rx_practise/tree/master/src/web 找到

小结

寥寥数语,并不足以概括Cycle.js,比如 MVI设计模式,Driver的编写,awesome-cycle 这些进阶项,还是留给看官们自行探索吧。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

您可能感兴趣的文章:

  • jQuery图片切换插件jquery.cycle.js使用示例
  • RxJS的入门指引和初步应用
  • 使用RxJS更优雅地进行定时请求详析
  • 如何用RxJS实现Redux Form
  • 关于RxJS Subject的学习笔记
  • Angular搜索场景中使用rxjs的操作符处理思路
  • Angular5升级RxJS到5.5.3报错:EmptyError: no elements in sequence的解决方法
  • angular.js4使用 RxJS 处理多个 Http 请求


  • 上一条:
    javascript系统时间设置操作示例
    下一条:
    vue安装遇到的5个报错及解决方法
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 使用 Alpine.js 排序插件对元素进行排序(0个评论)
    • 在js中使用jszip + file-saver实现批量下载OSS文件功能示例(0个评论)
    • 在vue中实现父页面按钮显示子组件中的el-dialog效果(0个评论)
    • 使用mock-server实现模拟接口对接流程步骤(0个评论)
    • vue项目打包程序实现把项目打包成一个exe可执行程序(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客