react-redux 开发实践与学习分享
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/j_bleach/article/details/78070539
redux简介
redux是一个js状态管理的库,由flux基础上开发出来,与flux的主要区别是只有一个store,关于store,后文会详述。在各大框架中均可使用,当然各个框架也有自己再度封装的状态管理库,如angular的ngrx,vue的vuex,而本文主要介绍的是react的react-redux。
示例介绍
本次演示的示例,是一个微信注册页面,主要想通过react-redux实现的功能是,当输入不合法的注册信息时,顶部出现错误提示信息,即:
通过路由进入主页面,主页面渲染的dom代码为:
render() {
// 这个组件是一个包裹组件,所有的路由跳转的页面都会以this.props.children的形式加载到本组件下
const {msg} = this.props;
return (
<div className="container">
<div ref="test" className="weui-toptips weui-toptips_warn"
style={{'display': msg.show ? 'block' : 'none'}}>{msg.text}</div>
<div className="page">{this.props.children}</div>
</div>
);
}
可以看到主页面比更没有直接写入注册页面,而由错误提示部分加子路由入口组成,注册页面是通过子路由嵌套进来的,而又因为react的数据没有向上回溯的能力(即单项数据流),因此这里选择状态管理的方式去显示错误提示信息。
开讲react-rudex
最初看文档的时候,有一种体验,就是各个模块(action,reducer,store)等等,都看明白了,但是具体想去完成功能的时候还是一脸懵逼,不知道如何下手,于是这次为了去更好的讲解示例,我决定反着来,先从示例入手,再去引出那些概念。
关联rudex和页面组件-connect
从之前主页面的代码可以看到,错误信息的显示是由组件的props传进来的,而主页面是如何获取相关的props的呢,答案是通过一个connect的函数。
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
connect是react组件做状态管理的核心,它将组件和redux中的所有状态值连接起来。这个函数接受四个参数,它们分别是 mapStateToProps,mapDispatchToProps,mergeProps和options。
mapStateToProps(state, ownProps)
第一个参数是获取redux仓库中的值的一个函数。为了方便快速理解,我们可以简单粗暴的认为他是js中getter,setter中的getter,这是一个用来从redux中获取值的函数,这个函数返回的值,可以在当前组件的props中拿到。
比如现在主页面需要知道,当前redux仓库中是否显示错误提示的相关信息时,有如下代码:
const mapStateToProps = (state) => {
return {
msg: state.tipMsg,//取reducer中的tipMsg
}
}
export default connect(mapStateToProps)(Main);
state就是redux中储存值的大对象,而现在需要的错误信息就是存储在tipMsg的字段当中。因为在主页面只会取值,而不会设置值,因此connect只需要这一个函数足够。
ownProps这里还可以穿第二个参数,第二个参数特指当前组件的props,可以用来做信息对比。本例没有用到。
mapDispatchToProps(dispatch, ownProps)
如果说mapStateToProps是一个getter的话,那么mapDispatchToProps就是一个setter,他触发了redux的相关行为,使得rudex可以保存记录一些你想要记录改变的状态和值。
具体到本例中,触发redux行为的操作在注册页面,因此注册页面添加如下代码:
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({
showTip: showTip//第二个showTip是一个action
}, dispatch);
}
export default connect((state) => state, mapDispatchToProps)(Main);
可以看到当注册页面执行showTip的函数时,就会触发redux中的showTip的操作,这个操作是提前定义好的。这里有两个showTip,第一个是指当前页面的函数名,第二个是指redux中定义好的行为,这两个showTip没有必要的联系,只是作为一个关系映射,名字可以不一样。
mergeProps(stateProps, dispatchProps, ownProps)
这个参数的作用是表示把redux中的props(即当中存储的值)和当前组件的props做合并,默认都是要合并的,可以忽略这个属性。
options
一个配置项属性,可以做相关的配置。自行翻译吧~。 [options] (Object) If specified, further customizes the behavior of the connector.
[pure = true] (Boolean): If true, implements shouldComponentUpdate and shallowly compares the result of mergeProps, preventing unnecessary updates, assuming that the component is a “pure” component and does not rely on any input or state other than its props and the selected Redux store’s state. Defaults to true.
[withRef = false] (Boolean): If true, stores a ref to the wrapped component instance and makes it available via getWrappedInstance() method. Defaults to false.
store
这个就是之前一直提到的redux的仓库。redux的管理的数据都存储在store中。 我们只需要知道,store就是一个存储仓库,react-redux只有一个store,所有的东西都存在这里,想要在react组件中用他首先需要去根页面把它注入进去。需要在根节点写入如下代码:
import React from 'react';
import {render} from 'react-dom'; // 渲染组件时需要
import {Provider} from 'react-redux'; // react和redux连接的桥梁,就是这个Provider
import store from './redux/store/store'; // 引入sotre
import route from './router/route'; // 所有定义好的路由
// 创建根组件
render(
<Provider store={store}>
{route}
</Provider>,
document.body.appendChild(document.createElement('div'))
);
这是链接redux,使组件可以访问仓库的基础。
action
export const showTip = (item) => {
return {
type: 'SHOW_TIP',
item
}
}
之前在注册页面,如果没有满足相关条件,则触发redux的行为。而这个行为就是action。action具体定义了项目中触发的行为类别,通过type属性来区别于不同的行为。对应到connect的函数参数中,就是mapDispatchToProps需要去save或者说change什么样的行为。
reducer
const tipMsg = (state = {text: '', show: false}, action) => {
switch (action.type) {
case 'SHOW_TIP':
return Object.assign({}, {
text: action.item.text,
show: action.item.show
});
default:
return state;
}
}
一个纯函数,通过判断是什么样的行为,来对相关的state做更改,这中间是不含任何变量的,即只要确定输入,就能知道输出。在mapStateToProps这个取值函数中,取的也就是相关reducer中返回的值。 触发相关action后的主页控制台:
至此,就完成了react-redux对于父子组件的通信,由子组件向上推送信息至父组件,触发相关的操作。
项目地址:https://github.com/jiwenjiang/react-weui (ps:注意此项目由yarn管理,而不是npm)
- 为什么网站需要用CDN来加速?
- Jmeter常用获取数据的几种方式
- [Silverlight 4 RC]RichTextBox概览
- WCF后续之旅(4):WCF Extension Point 概览
- Asp.Net无刷新上传并裁剪头像
- 用泛型的IEqualityComparer<T>接口去重复项
- python与office(一)
- Asp.net 后台添加CSS、JS、Meta标签(帮助类)
- 分享一下cookies操作(增、删、改、查)小经验
- [Silverlight 4 RC]WebBrowserBrush概览
- 一个例子理解C#位移
- WCF后续之旅(3): WCF Service Mode Layer 的中枢—Dispatcher
- silverlight 2 Random 随机数解决方案
- 开发中巧用Enum枚举类型
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Qt音视频开发23-通用视频控件
- 破解Mariadb5.5密码
- redis学习(七)
- 自己实现一个SAP WebClient UI Repository Information System
- ABAP,Java和JavaScript类的构造函数使用的一些陷阱
- Spring Security如何优雅的增加OAuth2协议授权模式
- 如何将自定义XML视图注入SAP Fiori Elements应用
- SAP UI5控件ID的生成逻辑原理解析
- 如何自定义SAP Spartacus店铺的界面颜色风格
- 如何自定义SAP Spartacus店铺的购物车图表css风格
- 数据库PostrageSQL-从源代码安装
- Django的中间件
- WPF 使用 Skia 绘制 WriteableBitmap 图片
- dotnet 在 UOS 国产系统上使用 MonoDevelop 创建 GTK 全平台带界面应用
- dotnet 在 UOS 国产系统上安装 MonoDevelop 开发工具