一、redux及其源码
不知不觉从vue转到react已经一年了,对于react的认识也从使用迈向了原理,本着学习的态度,写下这个系列,希望大神多多指点,也希望能给学弟学妹们带来一丝丝帮助。
1、初始化项目
首先让我们先初始化一下我们的项目,控制台执行:
npx create-react-app myName
其中myName是我们的项目名称可以随意根据自己的喜好命名,然后回车,这时候默默等待安装完毕即可
2、初始化页面目录配置
我这里删除了一些不必要的默认文件,您可以根据自己需求做优化:
1:在src目录下新建pages,store文件夹,在pages下新建index.jsx文件,在store文件夹下新建store.js文件
2:执行npm install --save redux
安装redux
3:让我们使用先使用一下redux吧:
index.jsx完整代码
import React, { Component } from 'react'
import store from '@/store/store'
export default class index extends Component {
componentDidMount() {
// 订阅,默认取调用一下react的forceUpdate方法,从新render一下
store.subscribe(() => {
this.forceUpdate()
})
}
add = () => {
store.dispatch({type:"ADD"})
}
minus = () => {
store.dispatch({type:"MINUS"})
}
render() {
return (
<div className="le_home">
redux源码学习
<p>{store.getState()} </p>
<button onClick={ this.add}>增加</button>
<button onClick={ this.minus}>减少</button>
</div>
)
}
}
复制代码
store下完整代码:
import { createStore } from 'redux'
function countReducer(state = 0, action) {
switch (action.type) {
case 'ADD':
return state+1
case 'MINUS':
return state-1
default:
return state
}
}
let store = createStore(countReducer)
export default store
复制代码
项目运行后我们点击按钮就可以看到数字的变化了,是不是很申请啊,下面让我们去发现一下redux的神秘吧!
3、在store文件夹下面创建myStore.js文件,这是我们自己的redux
一:先分析下createStore函数的结构
1:接收了一个参数(reducer)
2:有三个内置的方法,分别是subscribe(订阅),dispatch(派发),getState(获取)
二:这里我直接给出了代码,有详细的注释
export function createStore(reduce,enhancer) {
if (enhancer) {
return enhancer(createStore(reduce))
}
// 定义初始值
let currentData = undefined
// 保存监听函数
let currentLinser = []
// 获取值
function getState() {
return currentData
}
// 派发值
function dispatch(action) {
currentData = reduce(currentData, action)
currentLinser.forEach(a=>a())
}
// 订阅值,这里调用react的forceUpdate()方法让render从新渲染
function subscribe(cb) {
currentLinser.push(cb)
}
// 初始化的时候先派发一下就可以了,因为我们订阅的时候直接返回了初始值
dispatch({type:'dsfs'})
return {
getState,
dispatch,
subscribe
}
}
复制代码
好了到这里我们就完成了redux的基本功能了,是不是很简单啊
4、redux中间件
上面我们实现的redux是有一定的缺陷的,就是我们在派发的时候直接处理了action,无法去做一些逻辑的编写,那么如何优化这一现象呢,这时就需要redux的第二个重要函数applyMiddleware了,下面让我们一起实现下吧
首先让我们安装以下react-thunk中间件,并且使用它看看会发生什么吧!
控制台执行npm install --save react-thunk
1:在store.js代码下增加
import { createStore,applyMiddleware } from 'redux'
import thunk from "redux-thunk";
let store = createStore(countReducer,applyMiddleware(thunk))
复制代码
2:在index,jsx代码下增加
//修改add函数增加一些逻辑
add = () => {
store.dispatch(dispatch => {
//这里就可以任意挥发了
setTimeout(() => {
dispatch({type:"ADD"})
},1000)
})
}
复制代码
5、applyMiddleware函数的实现
在myStore.js下创建applyMiddleware函数
export function applyMiddleware(...middlewares) {
// 直接返回一个强化后的函数
return createStore => (...args) => {
const store = createStore(...args)
let dispatch = store.dispatch
const midApi = {
getState:store.getState,
dispatch:(...args)=>dispatch(...args)
}
// 获取状态值,派发action
const middlewareChain = middlewares.map(middleware => middleware(midApi))
// 聚合成一个函数,这里是一个经典责任链设计模式
dispatch = compose(...middlewareChain) (store.dispatch)
return {
...store,
dispatch
}
}
}
//聚合函数
export function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
数据reduce方法,不清楚的可以查阅一下,一是从左往右计算值,二是聚合函数
return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
复制代码
这里就基本实现了redux,是不是很简单啊,下面我就就要开始学习react-redux了,加油!!!