在react中使用vuex的示例代码


Posted in Javascript onJuly 30, 2018

前言

笔者最近在学习使用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判断)。

在react中使用vuex的示例代码

上图来自于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不再是梦!

原文地址

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

Javascript 相关文章推荐
Extjs中常用表单介绍与应用
Jun 07 Javascript
Javascript中定义方法的另类写法(批量定义js对象的方法)
Feb 25 Javascript
jquery根据属性和index来查找属性值并操作
Jul 25 Javascript
jQuery中find()方法用法实例
Jan 07 Javascript
网页挂马方式整理及详细介绍
Nov 03 Javascript
微信小程序 两种滑动方式(横向滑动,竖向滑动)详细及实例代码
Jan 13 Javascript
Angular实现搜索框及价格上下限功能
Jan 19 Javascript
Vuex实现计数器以及列表展示效果
Mar 10 Javascript
JavaScript基础之静态方法和实例方法分析
Dec 26 Javascript
jQuery实现鼠标滑动切换图片
May 27 jQuery
JavaScript+HTML实现学生信息管理系统
Apr 20 Javascript
介绍一下28个JS常用数组方法
May 06 Javascript
使用JS判断移动端手机横竖屏状态
Jul 30 #Javascript
详解如何在微信小程序中愉快地使用sass
Jul 30 #Javascript
详解JSON Web Token 入门教程
Jul 30 #Javascript
JS中Promise函数then的奥秘探究
Jul 30 #Javascript
浅析java线程中断的办法
Jul 29 #Javascript
还不懂递归?读完这篇文章保证你会懂
Jul 29 #Javascript
如何在js代码中消灭for循环实例详解
Jul 29 #Javascript
You might like
php中使用Akismet防止垃圾评论的代码
2011/06/10 PHP
php处理斐波那契数列非递归方法
2012/02/04 PHP
PHP排序算法的复习和总结
2012/02/15 PHP
php calender(日历)二个版本代码示例(解决2038问题)
2013/12/24 PHP
dedecms集成财付通支付接口
2014/12/28 PHP
php中session定期自动清理的方法
2015/11/12 PHP
php中array_column函数简单实现方法
2016/07/11 PHP
linux平台编译安装PHP7并安装Redis扩展与Swoole扩展实例教程
2016/09/30 PHP
window.location.href中url中数据量太大时的解决方法
2013/12/23 Javascript
jquery.ajax的url中传递中文乱码问题的解决方法
2014/02/07 Javascript
jquery实现邮箱自动补全功能示例分享
2014/02/17 Javascript
java和javascript获取word文档的书签位置对比
2014/06/19 Javascript
一个仿糯米弹框效果demo
2014/07/22 Javascript
javascript中活灵活现的Array对象详解
2016/11/30 Javascript
jQuery File Upload文件上传插件使用详解
2016/12/06 Javascript
在vue中使用css modules替代scroped的方法
2018/03/10 Javascript
AngularJS中的作用域实例分析
2018/05/16 Javascript
Vue.js递归组件实现组织架构树和选人功能
2019/07/04 Javascript
[30:51]DOTA2上海特级锦标赛主赛事日 - 3 胜者组第二轮#1Liquid VS MVP.Phx第一局
2016/03/04 DOTA
[43:26]完美世界DOTA2联赛PWL S2 Forest vs Rebirth 第二场 11.20
2020/11/23 DOTA
python中使用urllib2伪造HTTP报头的2个方法
2014/07/07 Python
python处理PHP数组文本文件实例
2014/09/18 Python
python中使用正则表达式的连接符示例代码
2017/10/10 Python
使用Flask集成bootstrap的方法
2018/07/24 Python
Python 运行.py文件和交互式运行代码的区别详解
2019/07/02 Python
使用python+whoosh实现全文检索
2019/12/09 Python
python如何实现不可变字典inmutabledict
2020/01/08 Python
使用python创建Excel工作簿及工作表过程图解
2020/05/27 Python
Java工程师面试集锦之Spring框架
2013/06/16 面试题
C++是不是类型安全的
2014/02/18 面试题
本科生的职业生涯规划范文
2014/01/09 职场文书
体育运动口号
2014/06/09 职场文书
2014年客服工作总结范文
2014/11/13 职场文书
pytorch 如何使用batch训练lstm网络
2021/05/28 Python
Python3 多线程(连接池)操作MySQL插入数据
2021/06/09 Python
聊聊redis-dump工具安装问题
2022/01/18 Redis