借鉴redux,实现一个react状态管理方案
react状态管理方案有很多,其中最简单的最常用的是redux。
redux实现
redux做状态管理,是利用reducer和action实现的state的更新。 如果想要用redux,需要几个步骤
- actions
创建actions.js
// actions.js export const SET_NAME = 'SET_NAME'; export const setName = (name) => { return { type: SET_NAME, name, } }
- reducer
创建reducers.js
// reducers.js import {SET_NAME} from './actions'; const nameState = (state = '', action) => { switch(action.type) { case SET_NAME: { return action.name; } default: { return state; } } } export default nameState;
- 入口文
项目的入口文件
// index.js import React from 'react' import { render } from 'react-dom' import { Provider } from 'react-redux' import { createStore } from 'redux' import rootReducer from './reducers' import App from './App' const store = createStore(rootReducer) render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') )
- App组件
业务组件代码
import React, { Component } from 'react'; import { connect } from 'react-redux'; import {setName} from './actions'; class App extends Component { constructor(props) { super(props); } handleClick() { this.props.setName('张三李四') } render() { return ( <div> {this.props.name} <button onClick={this.handleClick.bind(this)}>修改name</button> </div> ) } } const mapStateToProps = (state) => { return { name: state.name, }; }; const mapDispatchToProps = (dispatch) => { return { setName(name) { dispatch(setName(name)); } } } export default connect(mapStateToProps, mapDispatchToProps)(App);
redux实现原理
redux是状态管理工具,react-redux使得react组件能与redux结合。
Provider
Provider是一个高阶组件,他需要在最外层,才能实现store被所有子组件共享。
connect
connect方法是将react组件连接store的方法。connect方法会将组件使用到的state和需要触发的action映射到react组件的属性上。
详解请看react-redux文档
为什么不用redux
redux提供了非常系统完整的state管理方案,用文档里的一句话则是:
通过限制更新发生的时间和方式,Redux 试图让 state 的变化变得可预测.
因为他很完整,所以相对复杂,需要较多的配置。在小的项目中想要更简便的状态管理方案,所以抛弃redux,寻找其他方案。
xudox实现
- 确定用法
- 完整示例
- 原理简介
确定用法
目的就是使用起来最简单,因此我可能会这样用
// 组件中使用 import React, { Component } from 'react'; import {connect} from 'xubox'; class AA extends Component { constructor(props) { super(props) } handleClick() { // 给组件挂在setState$方法,在这里直接改变state值 this.props.setState$({ name: '张三李四' }) } render() { return ( <div> {this.props.name} <button onClick={this.handleClick.bind(this)}></button> </div> ) } } // 与redux一样,函数返回组件需要的state const mapStateToProps = (state) => { return { name: state.name, }; }; // 与redux一样用法,区别是只传递mapStateToProps一个参数 connect(mapStateToProps)(AA);
从代码看上去与redux好像,只不过少了dispatch缓解,改成了直接改变state。那其他设置呢?除了手动设置初始state值,其他不需要任何设置。
设置state的初始值
// 入口文件 import configureState from 'xubox'; configureState({ name: localStorage.getItem('name') || '无名氏' });
完整示例
- 入口文件
index.js
import React from 'react'; import ReactDOM from 'react-dom'; import App from './app.js' import configure from 'xudux'; // 初始state let state = { name: '无名氏', }; configure(state); ReactDOM.render( <App /> , document.getElementById('root'));
- 组件内
app.js
import React, { Component } from 'react'; import { connect } from 'xudux'; class App extends Component { constructor(props) { super(props); } handleClick() { this.props.setState$({ name: '张三李四', }); } render() { return ( <div> {this.props.name} <button onClick={this.handleClick.bind(this)}>修改name</button> </div> ) } } const mapStateToProps = (state) => { return { name: state.name, }; }; export default connect(mapStateToProps)(App);
简单的两部就完成了状态管理。示例为一个组件内state渲染后视图,视图发起事件改变state,state改变引发视图的重新渲染。多组件间的通信同理。
原理简介
简单介绍xudux原理。原理很简单,connect形成高阶组件,在高阶组件内部监听state的变化,如果state变化则引发传入的react组件props发生变化,从而重新渲染。redux大概也是这样的逻辑。
setState$方法:此方法其实是xudux内部更新state的方法,任何组件调用此方法会触发xudux中state更新,state更新会推送给所有组件,每个组件判断自身的state是否改变,从而决定react组件是否更新。
结尾
有兴趣的大佬可以尝试一下 github