内容简介:如果你曾经使用过类似本文通过一个简单的示例,学习通过不同的方式(如
如果你曾经使用过类似 Angular
框架的经验,你会发现这些框架集成了开发一个应用应该具备的所有功能,例如用于进行HTTP调用的服务( Angular
中的 $HTTP
)。
React
是一个视图层框架,用于构建用户界面。在 MVC
架构中,它仅仅负责视图部分。在实际的开发过程中,往往需要我们引入一些第三方组件,比如今天要说的 AJAX API
。
本文通过一个简单的示例,学习通过不同的方式(如 Axios
、 XMLHttpRequest
或 fetch API
)使用来进行 AJAX
请求(GET、POST、PUT和DELETE),以获取、创建、更新和删除数据。
AJAX API
有很多的方案, 你所做的就是选择合适的解决方案:
1、对 JavaScript
中 Promise
比较熟悉,可以使用 Axios 。
2、喜欢使用前沿标准,可以使用 fetch API
。
3、也可以使用 jQuery
,但不建议仅仅为了进行API调用而引入整个库。
可以直接使用 XMLHttpRequest 接口。
Fetch API的示例
我推荐使用 create-react-app
来创建应用,因为它省去了好多的配置。
npm install -g create-react-app
通过执行以下命令创建并启动我们的应用: react-ajax-demo
create-react-app react-ajax-demo cd react-ajax-demo npm start
Fetch API
下面引自 Mozilla MDN :
Fetch API 提供了一个获取资源的接口(包括跨域)。任何使用过 XMLHttpRequest 的人都能轻松上手,但新的API提供了更强大和灵活的功能集。
读取Reddit上发布的一些帖子, src/App.js
:
import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class App extends Component { constructor(props) { super(props); this.state = { posts: [] }; } fetchFirst(url) { var that = this; if (url) { fetch('https://www.reddit.com/r/' + url + '.json').then(function (response) { return response.json(); }).then(function (result) { that.setState({ posts: result.data.children, lastPostName: result.data.children[result.data.children.length - 1].data.name }); console.log(that.state.posts); }); } } componentWillMount() { this.fetchFirst("reactjs"); } render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h1 className="App-title">React AJAX Example</h1> </header> <p className="App-intro"> <ul> {this.state.posts.map(post => <li key={post.id}>{post.title}</li> )} </ul> </p> </div> ); } } export default App;
在 fetchFirst()
方法中,我们发起了一个GET请求:
fetch('https://www.reddit.com/r/' + url + '.json').then(function (response) { return response.json(); }).then(function (result) { console.log(result.data.children); });
API很简单,需要的唯一参数就是资源的URI。这里它是一个JSON文件,也可以是任何类型的资源,如图像或其他类型。
**fetch(url)**在默认情况下发送GET HTTP请求。
还可以通过第二个参数中指定方法名来调用其他HTTP方法,如POST、PUT或DELETE。
例如,使用 fetch()
发送POST请求:
var form = new FormData(document.getElementById('login-form')); fetch("/login", { method: "POST", body: form });
AJAX API调用时机
一个典型的 React
应用是一系列包含根组件、父组件以及子组件(以及子组件的子组件)的组件,这些组件可以可看作为一个树状结构。
这里会产生许多问题:
1、如何处理数据?
2、数据如何从组件流到其他组件?
3、最重要的是,在哪里放异步请求的代码?
componentWillMount()
是React生命周期的一个重要事件,执行时机在组件第一次渲染之前,在组件即将挂载时调用该事件。
前面的例子中,我们就是在 componentWillMount()
事件内部发起 AJAX
请求。
其实还有几个地方可以这么做:
1、 componentDidMount()
: 这是官方推荐的地方
2、 componentWillMount()
: 官方不推荐
3、 constructor()
:它被认为是反模式! 但是可以像 componentWillMount()
一样使用。
componentDidMount() vs componentWillMount()
componentWillMount()
方法在组件的第一次渲染之前被调用。任何人误以为这是获取数据的最佳场所。但事实并非如此!因为 fetch
调用是异步的,这意味着在组件渲染之前异步请求有可能还没返回。一般采取的做法是:在 constructor()
设置初始状态,为了 React
能正确地渲染组件,在异步请求返回后触发组件的重新渲染。
componentDidMount()
方法是在组件第一次渲染之后调用的,因此可以放心在这里执行任何异步代码,这些操作可以是获取服务器数据,也可以是操作DOM。
在实现服务端渲染时,componentWillMount()会调用两次,因此会有两次请求发送给服务器,这是一种浪费。而componentDidMount()只会在客户端调用一次。
我们对上面的示例做下改动:
componentDidMount() { this.fetchFirst("reactjs"); }
componentWillMount() vs constructor
从程序的角度分析,是否可以用 constructor
代替 componentWillMount()
?
表面上看确实是可以替代的,但这并不是一种正确的方式。
因为我们如果学过纯函数的话,都知道其实异步请求是一种典型的有副作用的非纯函数。如果组件构造函数中存非纯函数, React
会抛出一个警告, 而 componentWillMount()
中是允许非纯函数的。如果代码中需要更新其他组件中的状态,最好不要使用构造函数。
最后一个结论是:对于任何不产生副作用(如状态更新)的初始化代码使用构造函数,否则使用componentDidMount()。
组件之间通信
另一种方法是从父组件向子组件传递数据。当然,父组件也应该避免之前获取数据的方法,那么在哪里呢?父节点可以使用React路由器钩子(如 onEnter()
)获取数据,然后通过 props
将数据传递给子节点。
在本文示例中,由于只有一个组件,但这可以很容易地分解为以下内容:
Fetch.js
export default { fetchFirst: function(url){ fetch('https://www.reddit.com/r/' + url + '.json').then(function (response) { return response.json(); }).then(function (result) { return result.data.children; }); } }
RedditPost.js
import React from "react"; class RedditPost extends React.Component { constructor(props) { super(props); this.state = { title: props.title, id: props.id } } componentWillReceiveProps(nextProps) { this.setState(nextProps); } render() { <li key={this.state.id}>{this.state.title}</li> ); } } } RedditPost.propTypes = { id: React.PropTypes.number, title: React.PropTypes.string }; RedditPost.defaultProps = { id: null, title: "" }; export default RedditPost;
App.js
import fetchFirst from "./Fetch"; import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class App extends Component { constructor(props) { super(props); this.state = { posts: [] }; } componentDidMount() { fetchFirst("reactjs").then((posts)=>{ this.state.posts = posts; }); } render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h1 className="App-title">React AJAX Example</h1> </header> <p className="App-intro"> <ul> {this.state.posts.map(post => <RedditPost {...post}/> )} </ul> </p> </div> ); } } export default App;
使用Redux State Manager
第三种方法是使用 Redux
这样的状态管理器。
从代码中的任何地方获取数据,然后将数据存储在全局存储中,所有其他组件都可以使用这些数据。
关于对 Redux
的学习,你可以自行了解,也可以读一下我之前写的几篇文章:
2、重新思考Redux
结尾
越来越多的企业在构建自己的网站时开始注重体验、性能,出现了大量的单页面应用,将 AJAX
这种无刷技术发挥到了极致。而我们在使用 React
开发应用时可以有多种 AJAX
方案:
1、 使用XMLHttpRequest
,如果觉得复杂,可直接使用 jQuery
。
2、 Fetch API
, 现代浏览器都支持,老版浏览器需要使用 polyfills
。
3、 Axios
:一个基于 promise
的 HTTP
库, 可以用在浏览器和 node.js
中。
以上所述就是小编给大家介绍的《AJAX API三驾马车: Axios vs . jQuery和Fetch》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 屡试不爽的架构三架马车
- 大拐点:传统数据库会像马车一样被淘汰
- 更强、更稳、更高效:解读 etcd 技术升级的三驾马车
- Angular 7.0.0-beta 6 发布,前端框架三驾马车之一
- Angular 7.0.0-beta 6 发布,前端框架三驾马车之一
- 阿里巴巴 DevOps 的三架马车: 资源/运维/监控 | 技术运营专场活动
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
宇宙涟漪中的孩子
谢云宁 / 四川科学技术出版社 / 2017-11 / 28.00元
近未来。日冕科技公司通过建造围绕太阳的光幕搜集了近乎无穷的能源,这些能源主要用于地球上的网络空间建设。随着全球网络时间频率的不断提升,越来越多的人选择接驳进虚拟空间,体验现实中难以经历的丰富人生。 网络互动小说作者宁天穹一直自认为是这些人中普通的一员,有一天却被一名读者带进反抗组织,了解到日冕公司的各种秘密,并被告知自己的小说将在抵抗运动中起到重要作用。 起初他拒绝参与,但看到地球被笼......一起来看看 《宇宙涟漪中的孩子》 这本书的介绍吧!