react技术栈相关

## React

React方法绑定,实现在类定义的组件中绑定this上下文效果

bind方法

1
2
3
4
5
6
7
8
9
import React, { Component } from 'react';
class App extends Component {
handleClick(e, arg) {
console.log(e, arg);
}
render() {
return <button onClick={this.handleClick.bind(this, 'test')}>Test</button>;
}
}

构造器内声明

1
2
3
4
5
6
7
8
9
10
11
12
13
import React, { Component } from 'react';
class App extends Component {
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
console.log(e);
}
render() {
return <button onClick={this.handleClick}>Test</button>;
}
}

箭头函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React, { Component } from 'react';
class App extends Component {
const handleClick = (e) => {
console.log(e);
}
render() {
return <button onClick={this.handleClick}>Test</button>
}
}

// or,可传递参数 

import React, { Component } from 'react';
class App extends Component {
handleClick() {
console.log(this);
}
render() {
return <button onClick={(e) => this.handleClick(e)}>Test</button>
}
}

React组件生命周期

挂载

当组件实例被创建并插入DOM时,其生命周期调用顺序如下:

  • constructor()
  • static getDerivedStateFromProps()
  • render()
  • componentDidMount()

componentWillMount 即将过时,避免使用。

更新

当组件的 props 或 state 发生变化时触发更新,组件生命周期调用顺序如下:

  • static getDerivedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()

卸载

当组件从DOM中移除时会调用如下方法:

  • componentWillUnmount()

错误处理

当渲染过程,生命周期,或子组件函的构造函数中抛出错误时,会调用如下方法:

  • static getDerivedStateFromError()
  • componentDidCatch()

Reudx

Store

store 是保存数据的地方,整个应用只能有一个 store。

Redux 提供了 createStore 方法来生成 store。

1
2
import { createStore } from 'redux';
const store = createStore(reducer); // 要想生成 store, 必须传入一个 reducer.

State

Store 对象包含所有的数据。如果想得到某个时间点的数据,就要对 Store 生成快照。这种时点的数据集合,就叫 State。
获取当前时刻的 State,通过 Store.getState() 得到。

1
2
3
4
import { createStore } from 'redux';
const store = createStore(reducer);

const state = store.getState();

Redux 规定,一个 State 对应一个 View, 只要 State 相同, View 就相同。反之亦然、

Action

State 变化会导致 View 变化。但用户接触不到 State,只能接触到 View。所以 State 变化必须是 View 导致的。 Action 就是 View 发出的通知,表示 State 要发生变化了。
Action 是一个对象,其中 type 属性是必须的,表示 Action 的名称。

1
2
3
4
const action = {
type: 'ADD_TODO',
payload: 'Learn Redux'
};

改变 State 唯一的办法,就是使用 Action。

Action Creator

1
2
3
4
5
6
7
8
9
const ADD_TODO = '添加TODO';

function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
const action = addTodo('Learn Redux');

store.dispatch()

store.dispatch() 是 View 发出 Action 唯一方法。

Reducer

Store 收到 Action 后,必须给出一个新的 State,这样 View 才会发生变化,这种 State 的计算过程叫做 Reducer。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const defaultState = 0;
const reducer(state = defaultState, action) => {
switch(action.type) {
case 'ADD':
return state + action.payload;
default:
return state;
}
}

const state = reducer(1, {
type: 'ADD',
payload: 2
})

store.subscribe

Store 允许使用 store.subscribe 方法设置监听函数,一旦 State 发生变化,就自动执行这个函数。

1
2
3
4
import { createStore } from 'redux';
const store = createStore(reducer);

store.subscribe(listener);

combineReducer

Redux 提供了一个 combineReducer 方法,用于 Reducer 的拆分。只要定义好了各个子 Reducer 函数,用 combineReducer 将它们合成一个大的 Reducer.

1
2
3
4
5
6
7
8
import { combineReducer } from 'redux';
const chatReducer = combineReducer({
chatLog,
statusMessage,
userName,
});

export default todoApp;

React-Redux

UI组件

  • 只负责UI呈现,不带任何业务逻辑
  • 没有状态(无 state)
  • 不适用任何 Redux 的 API

容器组件

  • 负责管理数据和业务逻辑,不负责 UI 呈现
  • 带有内部状态
  • 使用 Redux 的 API

connect()

connnect() 方法用于从 UI 组件生成容器组件。

1
2
3
4
5
6
import { connect } from 'react-redux';
// ...
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps,
)(TodoList);

connect 方法接收两个参数:mapStateToProps & mapDispatchToProps。前者负责输入逻辑,将 state 映射到 UI 组件的参数(props),后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action。

mapStateToProps

mapStateToProps 是一个函数,用于建立一个从(外部的)state 对象到 (UI组件)props 对象的映射关系。

mapDispatchToProps

mapDispatchToProps 用来建立 UI 组件的参数到 store.dispatch 方法的映射。

Provider 组件

React-Redux 提供 Provider 组件,可以让容器组件拿到 state。

1
2
3
4
5
6
7
8
9
10
11
12
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import todoApp from './reducers';
import App from './components/App';

let store = createStore(todoApp);
render(
<Provider store={store}>
<App/>
</Provider>,
document.getElementById('root');
)

中间件

中间件是一个函数,对 store.dispatch 方法进行了改造,在发出 Action 和执行 Reducer 之间,添加了其他功能。

1
2
3
4
5
6
7
8
import { applyMiddleware, createStore } from 'redux';
import createLogger from 'redux-logger';
const logger = createLogger();

const store = createStore(
reducer,
applyMiddleware(logger);
)

注意:

  • createStore 方法可以接受整个应用的初始状态作为参数, applyMiddleware 就成为了第三个参数了。
    1
    2
    3
    4
    5
    const store = createStore(
    reducer,
    initial_state,
    applyMiddleware(logger),
    );
  • 中间件的次序有讲究。
    1
    2
    3
    4
    const store = createStore(
    reducer,
    applyMiddleware(thunk, promise, logger),
    )
    应用了中间件[A, B, C], 一个 action 的完整执行流程为: A -> B -> C -> dispatch -> C -> B -> A.

<Provider store>

<Provider store> 使组件层级中的 connect() 方法,都能获得 Redux store。正常情况下,根组件应该嵌套在 <Provider> 中才能使用 connect() 方法。

1
2
3
4
5
6
ReactDom.render(
<Provider store={store}>
<MyRootComponent />
</Provider>,
rootEl
)

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])

连接 React 组件与 Redux store。连接操作不会改变原来的组件类,返回一个新的已与 Redux store 连接的组件类。

Redux-Saga

Sagas 被实现为 Generator functions,它会 yield 对象到 redux-saga middleware。 被 yield 的对象都是一类指令,指令可被 middleware 解释执行。当 middleware 取得一个 yield 后的 Promise,middleware 会暂停 Saga,直到 Promise 完成。