01 - redux 使用及原理

162 阅读1分钟

redux

介绍:

Redux 是 JavaScript 状态容器,提供可预测化的状态管理。 (如果你需要一个 WordPress 框架,请查看 Redux Framework。)

可以让你构建一致化的应用,运行于不同的环境(客户端、服务器、原生应用),并且易于测试。不仅于此,它还提供 超爽的开发体验,比如有一个时间旅行调试器可以编辑后实时预览。

Redux 除了和 React 一起用外,还支持其它界面库。 它体小精悍(只有2kB,包括依赖)。

官网:www.redux.org.cn/

阮一峰 redux教程: www.ruanyifeng.com/blog/2016/0…

导出使用

// import { createStore } from 'redux'
import { createStore } from './util/store.js'
import { applyMiddleware } from 'redux'
import logger from 'redux-logger'
import thunk from 'redux-thunk'

function countReducer(state = 0, action) {
	switch (action.type) {
		case 'ADD':
			return state + 1
		case 'MINUS':
			return state - 1
		default:
			return state
	}
}
const store = createStore(countReducer, applyMiddleware(thunk, logger))
// applyMiddleware(thunk, logger) 支持传入函数进行操作、支持日志

export default store

页面使用

import React, { Component } from 'react'
import store from './store'
export default class ReduxPage extends Component {
	componentDidMount() {
		store.subscribe(() => {
			this.forceUpdate()
		})
	}
	add = () => {
		store.dispatch({
			type: 'ADD'
		})
	}
	minus = () => {
		store.dispatch({
			type: 'MINUS'
		})
	}

	asyAdd = () => {
		// 支持传入一个函数 // 可以获得 dispatch, getState
		store.dispatch((dispatch, getState) => {
			setTimeout(() => {
				console.log('now ', getState()) //sy-log
				dispatch({ type: 'ADD' })
			}, 1000)
		})
	}

	render() {
		console.log('store', store) //sy-log
		return (
			<div>
				{' '}
				<h3>ReduxPage</h3>
				<p>{store.getState()}</p>
				<button onClick={this.add}>add</button>
				<button onClick={this.minus}>minus</button> {/* <button onClick={this.minus}>minus</button>{' '} */}
				<button onClick={this.asyAdd}>asyAdd</button>{' '}
			</div>
		)
	}
}

原理 store.js


export default function createStore(reducer, enhancer) {
	if (enhancer) { // 插件
		return enhancer(createStore)(reducer) // 下章讲解
	}
	let currentState // 存储初始值
	let currentListeners = []

	function getState() {
		return currentState
	}

	function dispatch(action) {
		currentState = reducer(currentState, action)
		currentListeners.forEach((listener) => listener())
		return action
	}

	function subscribe(listener) {
		currentListeners.push(listener)
		return () => {
			const index = currentListeners.indexOf(listener)
			currentListeners.splice(index, 1)
		}
	}
	dispatch({
		type: 'init'
	})
	return {
		getState,
		dispatch,
		subscribe
	}
}