Cycle.js 的简单介绍
Cycle.js 是我们迄今为止有机会惊叹和困惑的最易用的 JavaScript FRP 框架。优点是它有很多训练轮来帮助你走上摇摇晃晃的道路。缺点是:实现起来容易理解起来难,而且文档也没什么帮助。
开始行动的最佳方式是使用 Cycle 自己的create-cycle-app(通过 NPM 或 Yarn 按名称安装)。您最终会得到类似下面所示的内容,但已具备启动开发服务器或部署构建所需的所有必要框架。我们对其进行了简化以便说明。
import {run} from '@cycle/run';
import {div, makeDOMDriver} from '@cycle/dom';
import xs from 'xstream';
const main = function(sources) {
const vtree$ = xs.of(
div('My Awesome Cycle.js app')
);
const sinks = {
DOM: vtree$
};
return sinks;
};
const drivers = {
DOM: makeDOMDriver('#app')
};
run(main, drivers);
? 来源?汇点?循环在环境理论的行业术语中是一种抽象概念。老实说,这种抽象概念不会带来多大帮助。将来源视为读取效果,即意图的产物,将汇点视为写入效果,即模型的产物。
Cycle.js 中的“循环”是指用户界面和应用程序的呈现逻辑之间的循环流。UI 是逻辑的输入。逻辑是 UI 的输入。很矛盾,不是吗?Cycle 的诀窍是,它知道如何播种这个程序化的衔尾蛇,并通过run
我们在上面导入的方法让轮子转动。
create-cycle-app 的初始输出有很多不足之处,这并不是说我们不喜欢简单。只是从一大堆静态的无样式文本中掌握下一步该做什么有点困难。因此,为了说明基本原理,我们制作了一个Cycle 版本的幻灯片应用。欢迎克隆该仓库或在 Glitch 上重新混合它以试用。
接下来是通过代码快速浏览一下 Cycle 旋转的原因。
流
const width$ = sources.DOM.select('.width').events('input')
.map(e => e.target.value).startWith(410);
...
input
这是一个流。它由类上的 DOM 源中接收到的事件组成width
。可以将其视为一个数组,但它包含的不是空间中的值,而是时间中的值。我们将startWith
其设置为值,410
因为否则我们会将 null 传递给下游正在消费的任何东西width$
。它$
什么也不做。这只是流的命名约定。
? 仅供参考:$$ 是流的流的惯例。
流
const vtree$ = xs.combine(index$, width$).map(([index, width]) =>
反应式流库的市场是买方市场。Create-cycle-app 附带了xstream
一个专为 Cycle by Cycle 的创建者打造的轻量级库。最简单的说,它可以制作如下流
const vtree$ = xs.of(
div([div('A virtual DOM tree stream?'), div('Yup.')])
);
它有详尽的文档,你可以让它很好地满足大多数用途,甚至不需要学习它所包含的 26 种方法中的一半。也就是说,你可以用你喜欢的任何库来代替它。
超脚本
import {input, div, p, img} from '@cycle/dom';
Cycle 使用基于Hyperscript构建的 DOM 抽象库。上面的导入对于任何来自 React 的人来说都应该很舒服。下面的实现……可能有点不太舒服。
div({style: {
textAlign: 'center',
fontFamily: 'sans-serif',
fontWeight: '300'
}}, [
div({style: {marginBottom: '20px'}}, [
p({style:{color: '#858576', fontSize: '32px'}},
assets.captions[index]
),
input(
{
style: {width: '100px', cursor: 'pointer'},
attrs: {
class: 'width',
type: 'range',
min: 40,
max: 720,
value: width
}
}
)
]),
div([
img({
style: {borderRadius: '12px', cursor: 'pointer'},
attrs: {
src: assets.slides[index],
alt: assets.captions[index],
width: `${width}px`
}
})
])
])
不,您不必使用内联样式。是的,您确实需要导出从单个元素向下延伸的树。
element(opts, children)
它比乍一看更直观,非常灵活,并且支持HTML 下的所有内容。是的,你能改用 JSX,但既然已经包含在内,为什么不尝试一下呢。
驱动程序
将驱动程序视为 Cycle 应用程序与其周围世界之间的桥梁,无论是通过 DOM 驱动程序与人类用户的连接,还是通过 HTTP 驱动程序与 XHR 的连接。
import {makeDOMDriver} from '@cycle/dom';
...
const drivers = {
DOM: makeDOMDriver('#app')
};
样板应用程序随 DOM 驱动程序一起提供,但您还可以安装许多其他驱动程序。 您也可以自己动手。
?? Cycle.js 在哲学上与其他框架截然不同,而且其本身就很深奥,不可能一下子就理解。我们会及时深入探讨这些主题以及许多其他主题,但这些应该足以让您入门。