React Conf 2017 干货总结 1: React + ES next = ♥
React Conf 2017在加利福尼亚州的圣克拉拉万豪酒店圆满落幕,这已经是Facebook举办的第三届React官方大会了。
虽然不能参会,但是作为前端开发者,我们当然不能错过这个绝佳的学习契机。
笔者利用清明假期,参看了YouTube上关于这次大会的记录。一共34个精彩演讲,对应34个视频。获益匪浅。
这里,将会作为一个系列,对其中的几篇演讲进行翻译和分析。并辅助以code demo,帮助大家理解。
欢迎关注我的简书或掘金账号,也欢迎在Github上floow,最新的大会code demo,便可第一时间掌握。
今天为大家介绍的是Ben Ilegbodu的主题:React + ES next = ♥
Ben Ilegbodu是“为数不多的”参会有色程序员,黑人程序员如同女性程序员一样凤毛麟角。但是,本次分享主题很有爱,很有营养,精彩程度丝毫不打折扣。如果你不了解React也不要紧,因为这次讲的是ES6、ES7在React中的应用。所以,其实是对下一代ES的普及和介绍。
本文将以
- Destructuring、
- Spread Opetator、
- Arrow Function、
- Promises、
- Async Functions
这几方面展开。并通过nodeJS实现一个兼具前端和后端的小型“评论/留言 发布阅读系统”。
建议看这篇文章的同时,结合视频一起研究:Ben Ilegbodu - React + ES next = ♥ - React Conf 2017
实现预览
如图,我们实现了如下的页面。这是一个前端+后端的全栈小项目。
当然,样式是极其简陋的。作为“粗糙”的程序员,实在懒得在页面上花时间。
es-next.png
我们可以在输入框内输入姓名和留言内容。并点击按钮提交。后台使用nodeJS express框架,实现对文件的读写更新。
app.post('/api/comments', function(req, res) {
fs.readFile(COMMENTS_FILE, function(err, data) {
if (err) {
console.error(err);
process.exit(1);
}
var comments = JSON.parse(data);
var newComment = {
id: Date.now(),
author: req.body.author,
text: req.body.text,
};
comments.push(newComment);
fs.writeFile(COMMENTS_FILE, JSON.stringify(comments, null, 4), function(err) {
if (err) {
console.error(err);
process.exit(1);
}
res.json(comments);
});
});
});
这是nodeJS的后端代码,如果不理解也没关系。
接下来我们继续回到演讲。
解构Destructuring
在我们的项目中,最初版存在这样的一段代码:
_handleCommentSubmit(comment) {
let comments = this.state.comments;
...
// remaining code
}
请务必记住这个_handleCommentSubmit函数,接下来的全文都是围绕他展开,并进行一步步拓展。
这个函数的逻辑是对新提交的comment进行处理,首先他需要从state中读取现有的comments数组。
在使用解构赋值的情况下,我们重构为:
_handleCommentSubmit(comment) {
let {comments} = this.state;
...
// remaining code
}
也许这还看不出来解构到底有什么作用,但是在逻辑多的时候,他是很有必要的。比如:
let author = this.state.author;
let text = this.state.text;
就可以写为:
let {author, text} = this.state;
如果需要改变变量名时,就可以从:
let authorName = this.state.author;
let fullText = this.state.text;
改为:
let {author: authorName, text: fullText} = this.state;
再举一个例子,在function component(React无状态组件编写的一种推荐形式)情况下:
function MyComponent(props) {
return (
<div style={props.style}>{props.children}</div>
)
}
<MyComponent style="dark">Stateless function!</MyComponent>
我们可以改写为:
function MyComponent({children, style}) {
return (
<div style={style}>{children}</div>
)
}
<MyComponent style="dark">Stateless function!</MyComponent>
展开符Spread Opetator
还记得上面那个_handleCommentSubmit函数吗?
接下来我们要进行扩充。首先我们将新提交的comment(即函数参数),添加一个时间戳作为id。接下来,
我们拿到旧的state.comments之后,就要将新的comment(包含id)加入到state.comments当中。
初版做法是:
_handleCommentSubmit(comment) {
let {comments} = this.state;
let newComment = comment;
newComment.id = Date.now();
let newComments = comments.concat([newComment]);
...
// setState + ajax stuffs
}
在使用展开符后,我们可以重构为:
_handleCommentSubmit(comment) {
let {comments} = this.state;
let newComment = {...comment, id: Date.now()};
let newComments = [...comments, newComment];
...
// setState + ajax stuffs
}
当然,展开符还有很多其他benefits;比如,平时我们可以使用Math.max方法对数组求出最大值:
var arrayOfValue = [33, 2, 9];
var maxValueFromArray = Math.max.apply(null, arrayOfValue)
这个思路利用了apply接受一个数组作为函数参数的特性。
使用展开符,我们就可以:
var arrayOfValue = [33, 2, 9];
var maxValueFromArray = Math.max(...arrayOfValue);
同理,我们可以这样扩充一个数组:
let values = [2, 3, 4];
let verbose = [1, ...values, 5];
当然,以上都是对数组的展开。
对对象属性的展开符的使用,也已经到了Stage3阶段。今后,我们可以这样写代码:
let warriors = {Steph: 95, Klay: 82, Draymond: 79};
let newWarriors = {
...warriors,
Kevin: 97
}
而不必再使用Object.assign进行对象的扩展。
箭头函数Arrow Function
箭头函数带来的好处无疑是对this的绑定。
现在再回到我们的_handleCommentSubmit函数。做完了初始化工作,我们需要将新的comment通过ajax,异步发送给后端。在成功的回调函数中,进行setState处理:
$.ajax({
url: this.props.url,
data: comment,
success: function(resJson) {
this.setState({comments: resJson})
}.bind(this)
})
有经验的同学注意到了我使用bind更改this指向的处理。
在ES6箭头函数下,我们可以直接:
$.ajax({
url: this.props.url,
data: comment,
success: (resJson) => {
this.setState({comments: resJson})
}
})
我们再展开看看箭头函数的几种用法(使用方式):
- 匿名函数,单参数情况,比如实现一个数组的各项平方:
let squares = [1, 2, 3].map(value => value * value);
- 匿名函数,多参数情况,比如实现一个数组的各项累加:
let sum = [9, 8, 7].reduce((prev, value) => prev + value, 0)
这时候,需要把参数放在括号之中。
- 非匿名函数,无返回值情况:
const alertUser = (message) => {
alert(message)
}
这时候,函数体用花括号围起来。
- 更复杂的情况,比如上面我们用到过的:
const MyComponent = ({children, style}) => (
<div style={style}>{children}</div>
)
Promises
上面的代码我们使用了jquery的ajax方法发送异步请求,这可能在某些情况下出现“回调地狱”的情况。为此,我们使用基于Promise的fetch方法,进行重构:
_handleCommentSubmit(comment) {
// ...
fetch(this.props.url, {
method: 'POST',
body: Json.stringify(comment)
})
.then((res)=>res.json())
.then((resJson)=>{
this.setState({comments: resJson})
})
.catch((ex)=>{
console.error(this.props.url, ex)
})
}
当然,我们可以把上述代码做的更抽象:
const fetchJson = (path, options) => {
fetch(`${DOMAIN}${path}`, options)
.then((res)=>res.json())
}
我们在拉取评论时,就可以:
const fetchComments = () => fetchJson('api/comments')
基于promises的fetch,让异步请求变的灵活可靠。
同时,我再安利一个基于promises的sleep函数:
const sleep = (delay = 0) => {
new Promise((resolve)=>{
setTimeout(resolve, delay)
})
}
sleep(3000)
.then(()=>getUniqueCommentAuthors())
.then((uniqueAuthors)=>{this.state({uniqueAuthors})})
回到我们的Project中,在后端nodeJS实现里,我们把所有的评论存在data/comments.json文件当中。
在渲染视图时,就不可避免地要进行对data/comments.json文件读取,这个过程也应该是异步完成的:
const readFile = (filePath) => (
new Promise((resolve, reject)=>{
fs.readFile(filePath, (err, data)=>{
if (err) {reject(err)}
resolve(data)
})
})
)
readFile('data/comments.json')
.then((data)=>console.log('Here is the data', data))
.catch((ex)=>console.log('Arg!', ex))
Async Functions
当然,Promises实现也有缺点。
更先进的方式,就是使用Async,回到我们的_handleCommentSubmit方法,我们可以重构为:
async _handleCommentSubmit(comment) {
try {
let res = await fetch(this.props.url, {
method: 'POST',
body: JSON.stringify(comment)
});
newComments = await res.json();
}
catch (ex) {
console.error(this.props.url, ex);
newComments = comments;
}
this.setState({comments: newComments});
}
总结
这篇演讲生动形象地阐释了React是怎样与ES next融合天衣无缝的。不论是React也好,还是ES也好,其实笔者认为说到底,都是为了更大限度地解放生产力。
欢迎读者与我交流,有任何问题可以留言。今后几天,将有更多新鲜的react conf视频翻译奉献给大家。
Happy Coding!
PS: 作者Github仓库,欢迎通过代码各种形式交流。
React Conf 2017 干货总结 1: React + ES next = ♥的更多相关文章
- 【腾讯Bugly干货分享】React移动web极致优化
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/579083d1c9da73584b02587d 最近一个季度,我们都在为手Q家校 ...
- React学习笔记-1-什么是react,react环境搭建以及第一个react实例
什么是react?react的官方网站:https://facebook.github.io/react/下图这个就是就是react的标志,非常巧合的是他和我们的github的编辑器Atom非常相似. ...
- React系列(一):React入门
React简介 1.由来 React是有Facebook开发出来用于构建前端界面的JS组件库,由于其背后的强大背景,使得这款库在技术开发上完全没有问题. 2.React的优势 解决大规模项目开发中数据 ...
- React Native是一套使用 React 构建 Native app 的编程框架
React Native是一套使用 React 构建 Native app 的编程框架 React Native at first sight what is React Native? 跟据官方的描 ...
- react.js 从零开始(七)React (虚拟)DOM
React 元素 React 中最主要的类型就是 ReactElement.它有四个属性:type,props,key 和ref.它没有方法,并且原型上什么都没有. 可以通过 React.create ...
- 如何使用TDD和React Testing Library构建健壮的React应用程序
如何使用TDD和React Testing Library构建健壮的React应用程序 当我开始学习React时,我努力的一件事就是以一种既有用又直观的方式来测试我的web应用程序. 每次我想测试它时 ...
- React环境配置(第一个React项目)
使用Webpack构建React项目 1. 使用NPM配置React环境 NPM及React安装自行百度 首先创建一个文件夹,the_first_React 进入到创建好的目录,npm init,然后 ...
- Unite 2017 干货整理 优化篇
Unite 2017 干货整理 优化篇 2017年05月16日 将Unite 2017的一些演讲做了整理. 本篇有内存,CPU.GC.UI.渲染性能指标.Tips几个小节. 内容持续整理中. 内存 ...
- Unite 2017 干货整理 同步篇
http://www.kisence.com/2017/05/17/unite-2017-gan-huo-zheng-li-tong-bu-pian/ Unite 2017 干货整理 同步篇 2017 ...
随机推荐
- IE设置信任站点和安全级别(bat文件)
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Ranges\Range1 ...
- Http/2 升级指南
[转]http://www.syyong.com/architecture/http2.html HTTP/2(最初名为HTTP/2.0)是 WWW 使用的 HTTP 网络协议的主要版本. 它来自早先 ...
- 【BZOJ2527】【POI2011】Meteors [整体二分]
Meteors Time Limit: 60 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 这个星球经常会下陨石雨.BI ...
- poj1379 Run Away
传送门:http://poj.org/problem?id=1379 [题解] 题目大意:求(0,0)->(X,Y)内的一个点,使得这个点到给定的n个点的最小距离最大. 模拟退火 一开始可以先把 ...
- opencv_人脸检测、模型训练、人脸识别
人脸检测.模型训练.人脸识别 2018-08-15 今天给大家带来一套人脸识别一个小案例,主要是帮助小伙伴们解决如何入门OpenCV人脸识别的问题,现在的AI行业比较火热,AI技术的使用比较广泛.就拿 ...
- 让VC6.0编译出来的程序支持XP样式或XP风格
(1)VC6.0编译出来的win32程序不支持winxp样式的原因:微软WINXP系统更新了Comctl32.dll(ver 6.0)这个“XP风格”的控件.为了保留传统的Windows界面风格,特地 ...
- Python阶段复习 - part 1 - Python基础练习题
1.实现1-100的所有的和 # 方法1: sum = 0 for i in range(1,101): sum += i print(sum) # 方法2: num1 = int(input('请输 ...
- jquery——通过name属性查找元素
Js代码 : $("div[id]") 选择所有含有id属性的div元素 $("input[name='newsletter']") 选择所有的name属性 ...
- ios 里如何处理四舍五入的问题
http://blog.sina.com.cn/s/blog_a2774bb10101293j.html 今天朋友问我一个问题,就是如何只舍不入.比如 float price = 0.126,怎么样才 ...
- linux服务与进程
linux服务与进程 http://www.cnblogs.com/jamesbd/p/3567654.html linux服务与进程 1.应用程序 2.服务脚本 3.配置文件 4.查看进程 5.查看 ...