内容简介:es6的语法简单的 javascripg函数也可以!彻底的模板,没有自己任何的数据,也没有生命周期方法. 纯粹依赖于输入.
es6的语法
class List extends React.Component { render() { return (<ul>{this.props.children}</ul>); } } 复制代码
简单的 javascripg函数也可以!
//Stateless function syntax const List = function(children) { return (<ul>{children}</ul>); }; //ES6 arrow syntax const List = (children) => (<ul>{children}</ul>); 复制代码
彻底的模板,没有自己任何的数据,也没有生命周期方法. 纯粹依赖于输入.
首先来定义一个 App Container
目的是最为一个函数接收 app sate 对象
import React from 'react'; import ReactDOM from 'react-dom'; const App = appState => (<div className="container"> <h1>App name</h1> <p>Some children here...</p> </div>); //这里定义了渲染的方法,作为 APP函数的属性,并且是柯理化的, 等待传入 dom 元素 App.render = R.curry((node, props) => ReactDOM.render(<App {...props}/>, node)); export default App; 复制代码
在纯函数中,state 必须要在外部管理,然后以 props 的形式传递给组件
.
下面看看这个解释的例子
Stateless Timer component
简单的 timer 组件只接受 secondsElapsed 参数:
import React from 'react'; export default ({ secondsElapsed }) => (<div className="well"> Seconds Elapsed: {secondsElapsed} </div>); 复制代码
添加到 APP 中
import React from 'react'; import ReactDOM from 'react-dom'; import R from 'ramda'; import Timer from './timer'; const App = appState => (<div className="container"> <h1>App name</h1> //Timer 只从父组件接受 props 作为自己的数据 <Timer secondsElapsed={appState.secondsElapsed} /> </div>); App.render = R.curry((node, props) => ReactDOM.render(<App {...props}/>, node)); export default App; 复制代码
最后创建main.js 文件,启动渲染过程
import App from './components/app'; //导入容器组件 // 我们已经有了柯理化的方法 //App.render = R.curry((node, props) => ReactDOM.render(<App {...props}/>, node)); //配置好渲染的目标元素 const render = App.render(document.getElementById('app')); //state 初始值 let appState = { secondsElapsed: 0 }; //first render 首次渲染 render(appState); //多次重复渲染 setInterval(() => { appState.secondsElapsed++; render(appState); }, 1000); 复制代码
对于上面的代码, 变化的是组件的 state, 渲染的目标元素是一直不变的, 所以我们用柯理化配置好一个工厂函数
//闭包再工作! const render = App.render(document.getElementById(‘app’)); 复制代码
柯理化返回的函数,等待传入 props
(props) => ReactDOM.render(...) 复制代码
只要 State发生变化,我们需要渲染时,只需要传递 state 就可以了
setInterval(() => { appState.secondsElapsed++; render(appState); }, 1000); 复制代码
每一秒钟, secondsElapsed 属性会递增1, 然后作为参数传递给 render 函数
现在可以实现 Redux 风格的 reduce 函数, reduce式的函数不能突变当前值
currentState->newState 复制代码
使用 Radma 的 Lenses 来实现
const secondsElapsedLens = R.lensProp('secondsElapsed'); const incSecondsElapsed = R.over(secondsElapsedLens, R.inc); setInterval(() => { appState = incSecondsElapsed(appState); render(appState); }, 1000); 复制代码
首先创建 Lens
:
const secondsElapsedLens = R.lensProp('secondsElapsed'); 复制代码
lens可以聚焦于给定的属性,不会针对特定的对象, 所以可以重用.
-
View
R.view(secondsElapsedLens, { secondsElapsed: 10 }); //=> 10 复制代码
-
Set
R.set(secondsElapsedLens, 11, { secondsElapsed: 10 }); //=> 11 复制代码
-
用给定的函数 Set
R.over(secondsElapsedLens, R.inc, { secondsElapsed: 10 }); //=> 11 复制代码
inSecondElapsed reducer 是一个偏应用函数(partial application), 这一行
const incSecondsElapsed = R.over(secondsElapsedLens, R.inc); 复制代码
会返回一个新的函数,一旦用appState 调用, 就会应用 R.inc在 lensed prop secondElapsed 上.
appState=incSecondElapsed(appState) 复制代码
组合 React stateless components
开篇提到,React 组件可以作为函数, 那么可以用 R.compose来 compose 这些函数吗? 当然是可以的
用 React.createClass 是这样的:
const TodoList = React.createClass({ render: function() { const createItem = function(item) { return (<li key={item.id}>{item.text}</li>); }; return (<div className="panel panel-default"> <div className="panel-body"> <ul> {this.props.items.map(createItem)} </ul> </div> </div>); } }); 复制代码
现在问题是: TodoList 可以由小的可重用部分 composition 而成吗? 可以的. 可以分为三个更小的组件
- 容器组件
const Container = children => (<div className="panel panel-default"> <div className="panel-body"> {children} </div> </div>); 复制代码
- 列表组件
const List = children => (<ul> {children} </ul>); 复制代码
- 列表项组件
const ListItem = ({ id, text }) => (<li key={id}> <span>{text}</span> </li>); 复制代码
现在一步一动,看看每一步的输出
Container(<h1>Hello World!</h1>); /** * <div className="panel panel-default"> * <div className="panel-body"> * <h1>Hello World!</h1> * </div> * </div> */ Container(List(<li>Hello World!</li>)); /** * <div className="panel panel-default"> * <div className="panel-body"> * <ul> * <li>Hello World!</li> * </ul> * </div> * </div> */ const TodoItem = { id: 123, text: 'Buy milk' }; Container(List(ListItem(TodoItem))); /** * <div className="panel panel-default"> * <div className="panel-body"> * <ul> * <li> * <span>Buy milk</span> * </li> * </ul> * </div> * </div> */ 复制代码
- Container(List(ListItem(TodoItem))) 这里我们把TodoItem 数据传给 ListItem, 然后结果作为 List 的参数, 返回的结果又作为 Container的参数
如果用 compose 函数,过程如下
R.compose(Container, List)(<li>Hello World!</li>); /** * <div className="panel panel-default"> * <div className="panel-body"> * <ul> * <li>Hello World!</li> * </ul> * </div> * </div> */ const ContainerWithList = R.compose(Container, List); R.compose(ContainerWithList, ListItem)({id: 123, text: 'Buy milk'}); /** * <div className="panel panel-default"> * <div className="panel-body"> * <ul> * <li> * <span>Buy milk</span> * </li> * </ul> * </div> * </div> */ const TodoItem = { id: 123, text: 'Buy milk' }; const TodoList = R.compose(Container, List, ListItem); TodoList(TodoItem); /** * <div className="panel panel-default"> * <div className="panel-body"> * <ul> * <li> * <span>Buy milk</span> * </li> * </ul> * </div> * </div> */ 复制代码
- const TodoList = R.compose(Container, List, ListItem)
列表的工厂函数,TodoList 组件可以看作为Container,List和 ListItem 的组合 现在 还只能接受一个参数, 需要可以接受一个数组
const mapTodos = function(todos) { return todos.map(function(todo) { return ListItem(todo); }); }; const TodoList = R.compose(Container, List, mapTodos); const mock = [ {id: 1, text: 'One'}, {id: 1, text: 'Two'}, {id: 1, text: 'Three'} ]; TodoList(mock); /** * <div className="panel panel-default"> * <div className="panel-body"> * <ul> * <li> * <span>One</span> * </li> * <li> * <span>Two</span> * </li> * <li> * <span>Three</span> * </li> * </ul> * </div> * </div> */ 复制代码
- mapTodos 可以有更简单的模式
//This return todos.map(function(todo) { return ListItem(todo); }); //Is the same as return todos.map(ListItem); //So the result would be const mapTodos = function(todos) { return todos.map(ListItem); }; //The same using Ramda const mapTodos = function(todos) { return R.map(ListItem, todos); }; //Now remember two things from Ramda docs: // - Ramda functions are automatically curried // - The parameters to Ramda functions are arranged to make it convenient for currying. // The data to be operated on is generally supplied last. //So: const mapTodos = R.map(ListItem); //At this point mapTodos variable is rendudant, we don't need it anymore: const TodoList = R.compose(Container, List, R.map(ListItem)); 复制代码
- const mapTodos = R.map(ListItem); Ramda 函数式自动柯理化的,所以代码是这样的, 等待传递数据数组,返回的数组的形式是
- {data.item} 组成的数组
完整的 TodoList 的代码就是
import React from 'React'; import R from 'ramda'; const Container = children => (<div className="panel panel-default"> <div className="panel-body"> {children} </div> </div>); const List = children => (<ul> {children} </ul>); const ListItem = ({ id, text }) => (<li key={id}> <span>{text}</span> </li>); const TodoList = R.compose(Container, List, R.map(ListItem)); export default TodoList; 复制代码
工厂配置好了,就等数据了
- 模拟一下 appState 的 todo 数据
let appState = { secondsElapsed: 0, todos: [ {id: 1, text: 'Buy milk'}, {id: 2, text: 'Go running'}, {id: 3, text: 'Rest'} ] }; 复制代码
- 在 App 组件中添加 TodoList 组件作为子组件
import TodoList from './todo-list'; const App = appState => (<div className="container"> <h1>App name</h1> <Timer secondsElapsed={appState.secondsElapsed} /> <TodoList todos={appState.todos} /> </div>); 复制代码
TodoList组件期待的参数是一个todos数组,
<TodoList todos={appState.todos} /> //const TodoList = R.compose(Container, List, R.map(ListItem)) 复制代码
React stateless component是作为函数的,所以我们也可以传递参数
TodoList({todos: appState.todos}); 复制代码
最好是传递单个参数,所以这种情况,再改进一下
const TodoList = R.compose(Container, List, R.map(ListItem), R.prop('todos')); 复制代码
调用就直接改为:
TodoList(appState) 复制代码
结束
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 基于 Laravel、Lumen 框架集成百度翻译、有道翻译、Google 翻译扩展包
- 腾讯发布人工智能辅助翻译 致敬人工翻译
- golang调用baidu翻译api实现自动翻译
- 监管机器翻译质量?且看阿里如何搭建翻译质量评估模型
- 机器翻译新突破:谷歌实现完全基于attention的翻译架构
- PendingIntent 是个啥?官方文档描述的很到位。我给翻译翻译
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
内容创业:内容、分发、赢利新模式
张贵泉、张洵瑒 / 电子工业出版社 / 2018-6 / 49
越来越多的内容平台、行业巨头、资本纷纷加入内容分发的战争中,竞争非常激烈。优质的原创性内容将成为行业中最宝贵的资源。在这样的行业形势下,如何把内容创业做好?如何提高自身竞争力?如何在这场战争中武装自己?是每一位内容创业者都应该认真考虑的问题。 《内容创业:内容、分发、赢利新模式》旨在帮助内容创业者解决这些问题,为想要进入内容行业的创业者出谋划策,手把手教大家如何更好地进行内容创业,获得更高的......一起来看看 《内容创业:内容、分发、赢利新模式》 这本书的介绍吧!