作者:Oral (沪江Web前端开发工程师)
本文原创翻译,有不当的地方欢迎指出。转载请指明出处。
当你问起有关AJAX与React时,老司机们首先就会告诉你:React其实是个没有网络请求/AJAX功能的view库。这种说法很容易理解,但对于当你仅想让你的React组件从服务器上获取数据时,是没啥帮助的。
事实上,有很多种方法可以满足你的需求。也许你自己也脑洞大开考虑过几个,但一旦走错了方向,那代码可就一团糟了。
好吧,这下你好奇了:到底什么才是正确的、值得首选的方法呢?
答案是……看情况~~~
下面为大家一一介绍我收集的在React里使用AJAX的四个好方法。不过要注意的是,得根据app的大小及复杂度,和你已使用的库和技术来决定该使用哪种方法。
1. 根组件(Root Component)方法
这是一种最简单的方法,因此它适用于简单或小型的应用。
通过这种方法,你可以建立单一根组件(父层组件)去分发所有AJAX请求,然后它会把AJAX响应数据存储进state里,以props方式传递到子组件。可以参考下官方教程上的实例。
官方教程上的实例
https://facebook.github.io/re...
此实例中的CommentBox组件就是个分发所有AJAX请求的根组件。
不过,我不大喜欢官方教程实例中的一点:它使用了jQuery去发送AJAX请求。
jQuery是个有很多功能的大库,因此仅因AJAX而引入它是没多大意义的。
我推荐使用fetch()这个简单、标准化的JavaScript 网络请求API,它已被Chrome、Firefox浏览器支持,并且可以通过使用fetch polyfill去兼容其他浏览器。如果想要更具体地了解,大家可以参考我的《AJAX库之对比》,也许这对你选择自己的AJAX库有点帮助。
AJAX库之对比
http://andrewhfarmer.com/ajax...
注意:如果你的项目有着很深的组件树结构(子组件层层嵌套下去),那么就会需要把数据从根组件一层一层传递至子组件,而这个传递数据之路将比较长。
适宜使用root component 方法的场景:
1、项目组件树比较简单 2、项目中没有使用Redux或flux
2. 容器组件方法(Container Components)
容器组件就是“为展示组件或其它容器组件提供数据和方法的组件”,如果你还没有听过这个概念,建议你可以先阅读下Dan Abramov的有关展示组件和容器组件的文章。
展示组件和容器组件
https://medium.com/@dan_abram...
容器组件方法与根组件方法很像,不同的是容器组件可以支持多组件与服务器端交互。(根组件方法仅支持通过单一组件与服务器端交互)
容器组件方法是这样工作的:对于每个需要从服务器拿到数据的展示组件来说,需要有个可以发送网络请求的容器组件来把请求到的数据通过props传递给子组件。
举个具体的栗子:你想要展示一个有着name和picture的用户简介。我们该怎么去做呢?接下来,我们一步步来:
1.建立一个展示组件:<UserProfile />, 这个组件可以接收到name 和profileImage 数据。但是这个组件一定不能有任何AJAX请求代码。 2.建立组件<UserProfileContainer /> ,这个组件用来接收urserId .它请求到用户的数据以后通过props传递给刚才创建的组件<UserProfile />。
这样用户简介展示就实现了。容器组件中的AJAX请求将会由简单的AJAX库发送出去,这里我推荐使用fetch()方法。
fetch()方法
http://andrewhfarmer.com/ajax...
适宜为网络请求使用容器组件方法的场景:
1.项目组件树比较深
2.项目中除了某些组件需要从服务器上获取数据,绝大多数组件是不需要的。
3.项目需要从多端或多个API中获取数据。
4.项目中没有使用Redux或flux. 或者与’异步操作’方法相比,你更喜欢使用容器组件方法来完成请求数据功能。
3.Redux Async Actions
Redux管理数据,而AJAX提供服务器上的数据,因此Redux 应用于处理网络请求。
如果使用Redux,就不要把AJAX放进React组件里面,而是要放进Async Actions里。
Async Actions
http://redux.js.org/docs/adva...
这里我还是推荐fetch()方法去处理实际网络请求,幸运地,Redux官方文档上也是使用fetch().文档中已有一个使用Redux、React和fetch()方法的实例
example reddit API.
http://redux.js.org/docs/adva...
如果你使用flux,那这个方法也是类似的——在actions中发送网络请求。
适宜使用Redux Async Actions的场景:
1.项目中正使用着Redux
2.项目中正使用着flux,使用方式也是类似的
4. Relay
通过Relay,你需要使用GraphQL声明React组件需要的数据,然后,Relay会自动下载数据并传递至组件的props中。
Relay很适用于一个大型应用中,但是对于使用者来说,还是需要比较丰富的前期知识储备的。你需要:
1.学习Relay和GraphQL.
2.使用GraphQL指定React组件的数据需求,而不是使用propTypes来指定
3.准备一台GraphQL服务器
Relay仅意味着要连接GraphQL服务器,因此它不会帮你连接任何第三方API.
目前,Relay仅能连接单一GraphQL服务器,因此,如果你要从多台服务器中获取数据,那Relay方法就不适用了。不过,将来有可能支持连接多台服务器,这个问题已经在github上讨论得热火朝天了。
github上讨论
https://github.com/facebook/r...
如果你要继续研究Relay方法,那Realy Playground 是个搞清楚它如何工作的好地方。
Realy Playground
https://facebook.github.io/re...
适宜使用Relay方法的场景:
1.想要创建一个大型应用而又比较关心Relay设计去解决的问题(https://facebook.github.io/react/blog/2015/05/01/graphql-introduction.html#why-invent-something-new)
2.项目中还没有建立JSON API
3.为项目准备一台GraphQL服务器
4.项目只会连接单一服务器
彩蛋:反模式
如果以上方法都是正确的,那么什么方法是错误的呢?下面我来介绍两种大家尽量要避免使用的方法。
反模式 1:在展示组件中使用AJAX请求
已经用作负责其他功能(如复杂界面渲染)的组件中就不要添加AJAX逻辑了,否则只会违反关注点分离的设计原则。
反模式2:ReactDOM.render()
你可以使用完全游离于React之外的AJAX逻辑,当数据无论何时更新时,调用ReactDOM.render()来更新页面。
ReactDOM.render()
https://facebook.github.io/re...
这个方法也许可以正常运行。将它以反模式方式提出来,是因为我坚信第一种根组件方法虽与其类似,但简洁多了。
结论:
使用React建立的应用都是模块化的,React会成为其中一个模块,AJAX库是另一个模块。而使用Rails和Angular框架的应用,Rails或Angular则不会成为应用中的模块。
iKcamp原创新书《移动Web前端高效开发实战》已在亚马逊、京东、当当开售。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。