react与后端通讯

react组件

当只考虑使用react组件与后端进行通讯时,一般在componentDidMount钩子函数里实现请求即可,componentDidMount是render渲染后触发,在这里可以进行DOM之类的操作。而react不带请求方法,需要引入插件,而使用JQ这类的有点冗余,而axios插件流行,且灵活度高,而且返回的结果为Promise,便于操作。

1
2

npm isntall axios --save

请求例子:

1
2
3
4
5
6
7
8
9
componentDidMount(){
axios.get('请求URL')
.then(function (response) {
// response.data返回数据
})
.catch(function (error) {
// 捕获异常,如reject之类的
})
}

axios的拦截器可以对请求装饰,如添加token,添加遮罩或处理一些公共的信息,如错误码跳转等,这些可以让项目更容易维护。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//添加请求拦截器
axios.interceptors.request.use(function(config){
//在发送请求之前做某事
return config;
},function(error){
//请求错误时做些事
return Promise.reject(error);
});

//添加响应拦截器
axios.interceptors.response.use(function(response){
//对响应数据做些事
return response;
},function(error){
//请求错误时做些事
return Promise.reject(error);
});

redux

当项目很复杂时需要使用redux进行数据的集中分发时那么数据的来源都是从redux里来,而这样前端与后端的通讯就要在redux里进行。
但redux的数据进行传送过程时同步的,那么就需要中间件转为异步操作,而redux的强大又体出来了,redux适配性很高,只要给它加个合适的中间件,即可方便使用。

1
npm install --save redux-thunk

redux-thunk在Redux的action对象被reducer函数处理之前,插入异步功能。
redux-thunk中间件可以让action创建函数先不返回一个action对象,而是返回一个函数,函数传递两个参数(dispatch,getState),在函数体内进行业务逻辑的封装。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

import {createStore, applyMiddleware} from 'redux';
import thunk from 'redux-thunk';

function count(state = 0, action) {
switch (action.type) {
case 'ADD':
return state + 1;
case 'REDUCER':
return state - 1;
default:
return state;
}
}
const store = createStore(count,applyMiddleware(thunk));

//action创建函数

function addIfOdd() {
return (dispatch, getState) => {
const currentValue = getState();
if (currentValue % 2 == 0) {
return false;
}
dispatch({
type: 'ADD'
})
}
}

高阶组件

高阶组件用于增强现有组件组件,好比装饰器模式一样。
简单来说,一个高阶组件就是一个函数,这个函数接受一个组件作为输入,然后返回一个新的组件作为结果,而且,返回的新组件拥有了输入组件所不具有的功能。

而高阶组件的实现有两种方式,代理方式与继承方式。

代理方式

代理方式就是以组件为参数传入返回一个新的组件。
代理方式的高阶组件,可以应用在下列场景中:
1、操纵 prop;
2、访问 ref;
3、抽取状态;
4、包装组件。

1
2
3
4
5
6
7
8
9
10
11
12
13

const newComponent = (Component, newProps)=>{
return calss Wrapper extends React.Component{
constructor(props){
super(props);
}
render(){
return (
<Component {...this.props} {...newProps} />
);
}
}
}

继承方式

继承方式的高阶组件采用继承关系关联作为参数的组件和返回的组件,假如传入的组件参数是 WrappedComponent,那么返回的组件就直接继承自 WrappedComponent。

继承方式的高阶组件可以应用于下列场景:
1、操纵 prop;
2、操纵生命周期函数。

而继承方式改变prop是很麻烦的,需要使用React.cloneElement复制一份组件并修改prop值。

1
2
3
4
5
6
7
8
9
const modyComponent = (WrappedComponent)=>{
return class NewComponent extends WrappedComponent{
render(){
const elem = super.render();
const newProps = {...this.props, style: {color: 'red'}};
return React.cloneElement(elem, newProps, elem.props.children);
}
}
}

从上面例子的比较可以看出来,各方面看来代理方式都要优于继承方式。

以函数为子组件

由于以上的高阶组件都有一个问题就是嵌套加深,都要在组件外包囊一层,而且固化prop,无法达到预期的灵活要求,而以函数为子组件就可以解决这个问题。
以函数为子组件其实就是在使用this.props.children获取嵌套在组件内的函数,然后传参调用返回组件。

弊端就是每次使用都要创建一个函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

calss Wrapper extend Component{
constructor(props){
super(props);
}
render(){
childFn = this.props.children(this.props);
return childFn;
}
}

// 一定要是函数
Wrapper.propTypes = {
children: React.PropTypes.func.isRequired
}

// 使用
<Wrapper>
{(aa)=><div>{aa}</div>}
</Wrapper>