在react中使用vuex的示例代码

时间:2021-05-25

前言

笔者最近在学习使用react,提到react就绕不过去redux。redux是一个状态管理架构,被广泛用于react项目中,但是redux并不是专为react而生,两者还需要react-redux建立一座桥梁。同时,redux架构规定只能发送同步action,要想发送异步action就需要结合中间件如redux-thunk、redux-saga等,所以说要想搞定redux还真是不容易啊,光名词就这么多。笔者以前也接触过一点vuex,vuex对笔者这样的菜鸡相对友好,但是vuex是和vue配套的,是不可能用在react中的,这辈子都别想用在react中。但是我不服,那么这篇文章就探索下如何制作一个可以在react中使用的类似vuex的状态管理工具,我将它取名为reux。

vuex <=> redux + react-redux + redux-saga

正文

响应式数据观测系统

vue的一大特色就是响应式数据观测系统,它可以在get数据时收集依赖,在set数据时触发更新。vuex借助于vue的数据观测系统,可以轻松的收集数据依赖,并且依赖可以精细到组件的粒度,也就是说某一状态改变时,只有依赖到这一状态的组件才会触发rerender,这样看来redux体系就比较傻,只要提交action,就会从根组件rerender(react-redux内部自动进行shouldCompoentUpdate判断)。

上图来自于vue官网对vuex架构的说明,链接。

上图中的component是vue component,只要vue component执行render,那么vuex的数据响应系统就可以自动的收集依赖,当状态改变时,依赖于此状态的组件就会重新渲染。既然我们要实现的是一个类vuex的状态管理工具,即支持以get的方式收集依赖,以set的方式触发更新,所以reux利用了vue的响应式数据观测系统,正所谓前人种树,后人乘凉。

如何收集依赖

我们已经有了响应式数据系统,接下来要解决的问题就是如何收集依赖,收集依赖必须要触发get,而触发get的前提是组件可以拿到store,因此第一步是向组件注入store。类似react-redux,reux提供了Provider使子组件可以拿到store。

class Provider extends Component { getChildContext() { return {store: this.props.store}; } render() { const { children } = this.props; return children; }}Provider.childContextTypes = { store: PropTypes.object};

相应的子组件可以context拿到store,如下

class Child extends Component { render() { // store => this.context.store }}Child.contextTypes = { store: PropTypes.object};

这样写的缺点显而易见,每个子组件都需要定义contextTypes,同样的类似于react-redux,reux提供了connect函数,用于映射state => props

const connect = (mapStateToProps = () => {}) => { return (WrappedComponent) => { const Wrapper = class extends Component { render() { const store = this.context.store; const props = Object.assign({}, this.props, mapStateToProps(store.state, this.props), {dispatch: store.dispatch, commit: store.commit}); return <WrappedComponent {...props} /> } } Wrapper.contextTypes = { store: PropTypes.object }; reaturn Wrapper; }}

这样一来,只要组件执行render方法,便会触发get钩子,从而使得store自动收集依赖,我们再想下依赖是什么,其实依赖应该是组件实例,那么当set钩子触发时,每个依赖(即组件实例)只要执行forceUpdate方法就可以达到rerender的效果。

但是问题是,get钩子触发时,如何确定依赖到底是谁呢?借鉴vue,我们定义一个stack,当componentWillMount时进栈,当componentDidMount时出栈

componentWillMount() { pushTarget(this);}componentDidMount() { popTarget(this);}

这样当get钩子触发时,当前target就是目标依赖。同时应当注意,当组件update时应当重新收集依赖,因为update之后依赖关系很可能已经变化了

update() { // 清空依赖 this.clear(); pushTarget(this); this.forceUpdate(() => { popTarget(this); })}

至此,我们的小目标已经完成了,在react中使用vuex不再是梦!

原文地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章