redux的组成部分
直接上图,从上图中可以看出,所有的数据(比如state)被保存在一个被称为store的容器中 → 在一个应用程序中只能有一个store。store本质上是一个状态树,保存了所有对象的状态。任何UI组件都可以直接从store访问特定对象的状态。要通过本地或远程组件更改状态,需要分发一个action。分发在这里意味着将可执行信息发送到store。当一个store接收到一个action,它将把这个action代理给相关的reducer。reducer是一个纯函数,它可以查看之前的状态,执行一个action并且返回一个新的状态。
最简单的案例
我们实现一个最基本的点击按钮加减操作
store/index.js
import { createStore } from 'redux';
const countReducer = (state = 0, action) => {
const {type, payload} = action
switch(type) {
case 'ADD':
return state + payload;
case 'MINUS':
return state - payload;
default:
return state
}
}
const store = createStore(
countReducer
)
export default store;
先创建一个store
ReduxPage.js
import React, { Component } from 'react'
import store from '../store/'
export default class ReduxPage extends Component {
componentDidMount() {
this.unsubscribe = store.subscribe(() => {
this.forceUpdate()
})
}
componentWillUnmount() {
if(this.unsubscribe) {
this.unsubscribe()
}
}
add = () => {
store.dispatch({type: 'ADD', payload: 1})
}
minus = () => {
store.dispatch({type: 'MINUS', payload: 1})
}
render() {
return(
<div>
<h3>Reduxpage</h3>
<p>{store.getState()}</p>
<button onClick={this.add}>同步+</button>
<button onClick={this.minus}>同步-</button>
</div>
)
}
}
好,我们已经实现了redux。就是这么简单。上面的有个注意的地方,就是一定要在更新的时候进行监听,不然无法更新Dom的内容。
我们再回顾一下基本的流程:store里面有一个counterReducer,它是一个纯函数,传入的是state,返回的是新的state,里面定义了修改state的规则,然后把这个counterReducer注入到store里面,我们就可以使用store定义的一些方法干一些事情了。在ReduxPage.js里面,我们用了store.getState()这个方法访问了state的值。当点击按钮的时候,我们会通过store.dispatch触发一个ation,counterReducer收到这个action以后。会根据action的type,来执行相应的修改规则,然后对state作出更新,当state更新的时候,store.subscribe()会监听state的变化,然后通过this.forceUpdate()更新了Dom,这样,一个完整的redux就实现了它应该实现的功能。
下面进入源码,我们去看看具体是怎么实现的
最简单的源码
我们需要实现一个createStore类,然后去实现它内部的几个方法
Jredux/createStore.js
export default function createStore(reducer) {
let currentState;
let currentlistenrs = [];
function getState() {
return currentState;
}
function dispatch(action) {
currentState = reducer(currentState, action)
currentlistenrs.forEach(listener => listener())
}
function subscribe(listener) {
currentlistenrs.push(listener)
return () => {
const index = currentlistenrs.indexOf(listener)
currentlistenrs.splice(index, 1)
}
}
// 初始化
dispatch({type: 'Jredux'});
return {
getState,
dispatch,
subscribe
}
}
就这么简单,一个redux的源码就写完了,我们用上面的这个代码也可以实现按钮加减的操作了。