- 引言
- 高阶组件
- 同步生成props
- 可观察的Props
- 访问父组件props
- 使用helper函数生成props流
- 编写默认props
- 总结
- 译者注
引言
本文主要专注使用frint-react包提供的observe高阶组件
尽管frint.js只是渲染库,同时支持React和Vue, 本文将会专注讨论React.js
为了帮助你理解这篇文章的大部分内容,建议阅读之前我们博客上的几篇文章
- 使用React.js渲染Frint.js应用
- 在React.js组件中如何访问Frint.js Provider组件
高阶组件
观察高阶组件的API十分简单:
import React from 'react';
import { observe } from 'frint-react';
function MyComponent(props) {
return ...;
}
const ObservedComponent = observe(fn)(MyComponent);
export default ObservedComponent;
observe接收函数fn, fn函数内部生成最终传递至目标组件的属性,然后返回接收组件为参数的函数实现观察功能
同步生成props
fn函数可以直接访问FrintJS应用实例:
const ObservedComponent = observe(function(app){
// this will be the `props` in MyComponent
return {};
})(MyComponent);
因为可以访问应用实例,就可以直接获取实例内部属性,包括: providers
const ObservedComponent = observe(function(app){
return {
appName: app.getName(),
foo: app.get('foo')
};
})(MyComponent);
MyComponent组件将会接收appName和foo props属性
可观察的Props
observe高阶组件十分强大,可以直接將Rxjs 被观察对象作为流返回属性
想想随着时间变化的定时器:
import { interval } from 'rxjs/observable/interval';
const interval$ = interval(1000); // 每秒触发
可以把流转换下,转换成组件可以接受的属性兼容对象。
import { interval } from 'rxjs/observable/interval';
import { map } from 'rxjs/operators/map';
const interval$ = interval(1000);
const props$ = interval$.pipe(
map(x => ({ interval: x }))
);
这里创建了一个新的props可观察对象,將interval映射为定时触发的{interval: 1}结构。
现在可以用observe连接组件
import { interval } from 'rxjs/observable/interval';
import { map } from 'rxjs/operators/map';
const ObservedComponent = observe(function (app) {
const interval$ = interval(1000);
return interval$.pipe(
map(x => ({ interval: x }))
);
})(MyComponent);
组件渲染时,MyComponent将会接收每秒增长的interval属性,触发重新渲染
访问父组件props
在返回可观察props之前,可能需要访问父组件的props属性
React中,从父组件传递下来的props属性随时都会变化。
正因为属性不断变化,observe高阶组件可以直接访问父组件props可观察对象:
const ObservedComponent = observe(function (app, props$) {
// ...
})(MyComponent);
函数接收FrintJS实例参数和props$两个参数,props作为可观察对象从父组件传递下来。
使用helper函数生成props流
上面的例子已经很简单,只有一个可观察对象。随着应用功能增加,会有数倍的参数。
当你需要接收多个可观察对象,最后返回一个props流。
可以用frint-react中的streamProps辅助函数实现。
如果你是Rxjs大牛,可以忽略这部分
streamProps函数通过链式调用不断维持设置操作,设置完成所有值后,生成一个可观察对象
import { observe, streamProps } from 'frint-react';
const ObservedComponent = observe(function (app, props$) {
return streamProps()
// 同步数据
.set('foo', 'foo value')
.set({ bar: 'bar value' })
// 来自其他可观察对象值
.set(
interval$, // rest of the arguments are mappers
x => ({ interval: x })
)
.set(
props$,
parentProps => parentProps.somePropName,
somePropName => ({ baz: somePropName })
)
// 生成一个props流
.get$();
})(MyComponent);
上面的例子生成了一个props流,包括四个值:
- foo, 值时foo value
- bar, 值时bar value
- interval, 值为持续增长的整形数字
- baz 是从父组件传递的somePropName属性值
这些属性都可以在MyComponent中访问。
编写默认props
由于可观察对象是异步的,某些对象可能不会立即出发。
在新的props生成之前,需要传递默认值到目标组件中。
streamProps辅助函数接收一个可选参数,可以传递默认值:
import { streamProps } from 'frint-react';
const defaultProps = {
foo: 'n/a',
bar: 'n/a',
baz: 'n/a',
};
const props$ = streamProps(defaultProps)
.set(...)
.get$();
所有属性初始值都是n/a, 一旦可观察对象执行完,props属性都会更新流到目标组件
总结
总得来说,observe高阶组件做了这几件事:
- 包装目标组件,返回新被观察组件
- 提供FrintJS应用实例访问
- 提供父组件props属性观察对象访问
- 允许通过同步或者异步Observable的方式生成目标组件可访问的新props属性
这种方式帮助和鼓励开发者尽可能编写无状态React组件,隔离任何业务逻辑,只处理props属性。
如果你又任何想法可以关注我们的Twitter
译者注
原文链接
因译者水平有限,如有错误,欢迎指正交流