一直是 Redux 的死忠党, 但使用过 vuex 后, 感叹于 Vuex 上手之快, 于是萌生了写一个能在 React 里使用的类 Vuex 库, 暂时取名 Ruex https://github.com/mcdyzg/ruex .
如何使用
一: 创建 Store 实例:
与 vuex 一样, 使用单一状态树 (一个对象) 包含全部的应用层级状态(store).
store 可配置 state,mutations,actions 和 modules 属性:
state : 存放数据
mutations : 更改 state 的唯一方法是提交 mutation
actions :Action 提交的是 mutation, 而不是直接变更状态. Action 可以包含任意异步操作, 触发 mutation, 触发其他 actions.
支持中间件: 中间件会在每次 mutation 触发前后执行.
- store.js: import {
- createStore
- }
- from 'ruex'const state = {
- total_num: 1111,
- }
- const mutations = {
- add(state, payload) {
- state.total_num += payload
- },
- double(state, payload) {
state.total_num = state.total_num*payload
- },
- }
- const actions = {
- addAsync({state,commit,rootState,dispatch},payload){
- setTimeout(()=>{
- commit('add',payload)
- },1000)
- },
- addPromise({state,commit,rootState,dispatch},payload){
- return fetch('https://api.github.com/search/users?q=haha').then(res=>res.json())
- .then(res=>{
- commit('add',1)
dispatch('addAsync',1)
- })
- },
- doubleAsync({state,commit,rootState,dispatch},payload){
- setTimeout(()=>{
- commit('double',2)
- },1000)
- },
- doublePromise({state,commit,rootState,dispatch},payload){
- return fetch('https://api.github.com/search/users?q=haha').then(res=>res.json())
- .then(res=>{
- commit('double',2)
dispatch('doubleAsync',2)
- })
- },
- }
- // middleware
- const logger = (store) => (next) => (mutation,payload) =>{
- console.group('before emit mutation',store.getState())
- let result = next(mutation,payload)
- console.log('after emit mutation', store.getState())
- console.groupEnd()
- }
- // create store instance
- const store = createStore({
- state,
mutations,
actions,
- },[logger])
- export default store
将 Store 实例绑定到组件上
ruex 提供 Provider 方便 store 实例注册到全局 context 上. 类似 react-redux 的方式.
- App.js:
- import React from 'react'
- import {Provider} from 'ruex'
- import store from './store.js'
- class App extends React.Component{
- render(){
- return (
- <Provider store={store}>
- <Child1/>
- </Provider>
- )
- }
- }
使用或修改 store 上数据
store 绑定完成后, 在组件中就可以使用 state 上的数据, 并且可以通过触发 mutation 或 action 修改 state. 具体的方式参考 react-redux 的绑定方式: 使用 connect 高阶组件.
- Child1.js:
- import React, {PureComponent} from 'react'
- import {connect} from 'ruex'
- class Chlid1 extends PureComponent {
- state = {}
- constructor(props) {
- super(props);
- }
- render() {
- const {
total_num,
- } = this.props
- return (
- <div className=''>
- <div className="">
- total_num: {total_num}
- </div>
- <button onClick={this.props.add.bind(this,1)}>mutation:add</button>
- <button onClick={this.props.addAsync.bind(this,1)}>action:addAsync</button>
- <button onClick={this.props.addPromise.bind(this,1)}>action:addPromise</button>
- <br />
- <button onClick={this.props.double.bind(this,2)}>mutation:double</button>
- <button onClick={this.props.doubleAsync.bind(this,2)}>action:doubleAsync</button>
- <button onClick={this.props.doublePromise.bind(this,2)}>action:doublePromise</button>
- </div>)
- }
- }
- const mapStateToProps = (state) => ({
- total_num:state.total_num,
- })
- const mapMutationsToProps = ['add','double']
- const mapActionsToProps = ['addAsync','addPromise','doubleAsync','doublePromise']
- export default connect(
mapStateToProps,
mapMutationsToProps,
mapActionsToProps,
)(Chlid1)
API:
mapStateToProps : 将 state 上的数据绑定到当前组件的 props 上.
mapMutationsToProps : 将 mutation 绑定到 props 上. 例如: 调用时通过 this.props.add(data)的方式即可触发 mutation,data 参数会被 mutaion 的 payload 参数接收.
mapActionsToProps : 将 action 绑定到 props 上.
内部实现
ruex 内部使用 immer 维护 store 状态更新, 因此在 mutation 中, 可以通过直接修改对象的属性更改状态, 而不需要返回一个新的对象. 例如:
- const state = {
- obj:{
- name:'aaaa'
- }
- }
- const mutations = {
- changeName(state,payload){
- state.obj.name = 'bbbb'
- // instead of
- // state.obj = {name:'bbbb'}
- },
- }
支持 modules(暂不支持 namespace)
支持中间件. 注: actions 已实现类似 redux-thunk 的功能
来源: http://www.jb51.net/article/137614.htm