react-redux
1. 首先redux,与react是两个独立的个体,项目中可以只用react,也可以只用redux
1.1 react-redux: 是一个redux作者专门为react制作的 redux, 增加了新的api,辅助react使用redux
React-Redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component)。
2. UI组件
2.1 特征:
只负责 UI 的呈现,不带有任何业务逻辑
没有状态(即不使用this.state这个变量)
所有数据都由参数(this.props)提供
不使用任何 Redux 的 API
特征的意思就是:只展示数据,父亲传什么给他,他就展示什么,没有点击,拖动之类的事件逻辑,
注意,他并不是没有事件,只是把事件的要执行的函数放在容器组件里,
3.容器组件
3.1 容器组件与ui组件恰恰相反
负责管理数据和业务逻辑,不负责 UI 的呈现
带有内部状态
使用 Redux 的 API
意思就是:有事件响应,例如onClick后改变元素class
2 && 3 总结: 容器组价包裹UI组件,容器组件通过改变this.state, 改变子UI组件的this.props,从而达到改变ui
React-Redux 规定,所有的 UI 组件都由用户提供,容器组件则是由 React-Redux 自动生成。也就是说,用户负责视觉层,状态管理则是全部交给它。
4.react-redux提供的方法
4.1 connect() : 为UI组件生成包裹它的容器组件
import { connect } from 'react-redux'
const VisibleTodoList = connect()(TodoList);
4.1.1 为UI组件(TodoList)生成容器组件(VisibleTodoList),用于管理TodoList的数据,样式
4.1.2 管理之前,首先要告诉它怎么管理
//(1)输入逻辑:外部的数据(即state对象)如何转换为 UI 组件的参数
//(2)输出逻辑:用户发出的动作如何变为 Action 对象,从 UI 组件传出去。 import { connect } from 'react-redux' const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
上面代码中,connect
方法接受两个参数:mapStateToProps
和mapDispatchToProps
。它们定义了 UI 组件的业务逻辑。
前者负责输入逻辑,即将state
映射到 UI 组件的参数(props
),后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action。
4.2 mapStateToProps()
4.2.0 若省略该参数,组件将不订阅store,不引发更新
4.2.1 会订阅 Store,每当state
更新的时候,就会自动执行,重新计算 UI 组件的参数,从而触发 UI 组件的重新渲染。
4.2.2 是一个函数。它的作用就是像它的名字那样,建立一个从(外部的)state
对象到(UI 组件的)props
对象的映射关系
4.2.3 执行之后返回一个对象,每一个key 对应着UI组件的 props
const mapStateToProps = (state) => {
return {
todos: getVisibleTodos(state.todos, state.visibilityFilter)
}
} //这类似于一个reducer
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case 'SHOW_ALL':
return todos
case 'SHOW_COMPLETED':
return todos.filter(t => t.completed)
case 'SHOW_ACTIVE':
return todos.filter(t => !t.completed)
default:
throw new Error('Unknown filter: ' + filter)
}
}
4.2.4 mapStateToProps
的第一个参数总是state
对象,还可以使用第二个参数,代表容器组件的props
对对象,而且只要组件接收到新的 props,mapStateToProps
也会被调用
// 容器组件的代码
// <FilterLink filter="SHOW_ALL">
// All
// </FilterLink> const mapStateToProps = (state, ownProps) => {
return {
active: ownProps.filter === state.visibilityFilter
}
}
//使用ownProps作为参数后,如果容器组件的参数发生变化,也会引发 UI 组件重新渲染
4.2.5 connect
方法可以省略mapStateToProps
参数,那样的话,UI 组件就不会订阅Store,就是说 Store 的更新不会引起 UI 组件的更新。
4.3 mapDispatchToProps()
4.3.0 若connect()省略该参数,dispatch会以props属性的形式传入ui组件
4.3.1 两种形式:函数,会得到dispatch
和ownProps
(容器组件的props
对象)两个参数,然后返回一个对象,每一个key对应着UI组件的事件,发出怎样的action
const mapDispatchToProps = (
dispatch,
ownProps
) => {
return {
onClick: () => {
dispatch({
type: 'SET_VISIBILITY_FILTER',
filter: ownProps.filter
});
}
};
}
4.3.2 两种形式: 对象 ,它的每个键名也是对应 UI 组件的同名参数,键值应该是一个函数,会被当作 Action creator ,返回的 Action 会由 Redux 自动发出
const mapDispatchToProps = {
onClick: (filter) => {
type: 'SET_VISIBILITY_FILTER',
filter: filter
};
}
两者的区别:1.函数可以获得ownProps,给每一个事件使用,对象必须在事件函数中加入自己的参数,
2.函数自己发出dispatch,对象由redux自动发出
5.<Provider> 组件
5.1 connect
方法生成容器组件以后,需要让容器组件拿到state
对象,才能生成 UI 组件的参数。
那么要怎样才能拿到state呢?
a: 将state
对象作为参数,传入容器组件(props)。但是,这样做比较麻烦,尤其是容器组件可能在很深的层级,一级级将state
传下去就很麻烦。
b: React-Redux 提供Provider
组件,可以让容器组件拿到state;
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from './reducers'
import App from './components/App' let store = createStore(todoApp); render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
上面代码中,Provider
在根组件外面包了一层,这样一来,App
的所有子组件就默认都可以拿到state
了。
5.2 它的原理是React
组件的context
属性,请看源码。
5.2.1 Provider 设置context ,需要使用getChildContext,以及childContextTypes
class Provider extends Component {
getChildContext() {
return {
store: this.props.store
};
}
render() {
return this.props.children;
}
} Provider.childContextTypes = {
store: React.PropTypes.object
}
5.2.2 子组件获取context, 如下 context 已经注入每一个自组件,成为一个属性,this.context
class VisibleTodoList extends Component {
componentDidMount() {
const { store } = this.context;
this.unsubscribe = store.subscribe(() =>
this.forceUpdate()
);
} render() {
const props = this.props;
const { store } = this.context;
const state = store.getState();
// ...
}
} VisibleTodoList.contextTypes = {
store: React.PropTypes.object
}
注意:以上context是 React-Redux
自动生成的容器组件的代码,就类似上面这样,从而拿到store
。
6.实例:
6.1 计数器
import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'
import { createStore } from 'redux'
import { Provider, connect } from 'react-redux' /*********************** 第一步:纯UI组件 ************************/
// React component
class Counter extends Component {
render() {
const { value, onIncreaseClick } = this.props
return (
<div>
<span>{value}</span>
<button onClick={onIncreaseClick}>Increase</button>
</div>
)
}
} Counter.propTypes = {
value: PropTypes.number.isRequired,
onIncreaseClick: PropTypes.func.isRequired
} /************* 第二步 定义mapStateToProps && mapDispatchToProps *******/
// Map Redux state to component props
function mapStateToProps(state) {
return {
value: state.count
}
} // Map Redux actions to component props
function mapDispatchToProps(dispatch) {
return {
onIncreaseClick: () => dispatch(increaseAction)
}
}
// Action
const increaseAction = { type: 'increase' } /************第三步:调用connect ****************/
// Connected Component
const App = connect(
mapStateToProps,
mapDispatchToProps
)(Counter) /* ************ 第四步: 定义组件的reducer ****************/
// Reducer
function counter(state = { count: }, action) {
const count = state.count
switch (action.type) {
case 'increase':
return { count: count + }
default:
return state
}
} /* ************* 最后: 生成store 并使用Provider 包裹 ***********/ // Store
const store = createStore(counter) ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
react-redux的更多相关文章
- webpack+react+redux+es6开发模式
一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...
- react+redux教程(六)redux服务端渲染流程
今天,我们要讲解的是react+redux服务端渲染.个人认为,react击败angular的真正“杀手锏”就是服务端渲染.我们为什么要实现服务端渲染,主要是为了SEO. 例子 例子仍然是官方的计数器 ...
- react+redux教程(五)异步、单一state树结构、componentWillReceiveProps
今天,我们要讲解的是异步.单一state树结构.componentWillReceiveProps这三个知识点. 例子 这个例子是官方的例子,主要是从Reddit中请求新闻列表来显示,可以切换reac ...
- react+redux官方实例TODO从最简单的入门(6)-- 完结
通过实现了增-->删-->改-->查,对react结合redux的机制差不多已经了解,那么把剩下的功能一起完成吧 全选 1.声明状态,这个是全选状态 2.action约定 3.red ...
- react+redux官方实例TODO从最简单的入门(1)-- 前言
刚进公司的时候,一点react不会,有一个需求要改,重构页面!!!完全懵逼,一点不知道怎么办!然后就去官方文档,花了一周时间,就纯react实现了页面重构,总体来说,react还是比较简单的,由于当初 ...
- 重写官方TodoList,对于初学react+redux的人来说,很有好处
虽然官网的TodoList的例子写的很详细,但是都是一步到位,就是给你一个action,好家伙,全部都写好了,给你一个reducer,所有功能也是都写好了,但是我们这些小白怎么可能一下就消化那么多,那 ...
- react+redux教程(四)undo、devtools、router
上节课,我们介绍了一些es6的新语法:react+redux教程(三)reduce().filter().map().some().every()....展开属性 今天我们通过解读redux-undo ...
- react+redux教程(三)reduce()、filter()、map()、some()、every()、...展开属性
reduce().filter().map().some().every()....展开属性 这些概念属于es5.es6中的语法,跟react+redux并没有什么联系,我们直接在https:// ...
- react+redux教程(二)redux的单一状态树完全替代了react的状态机?
上篇react+redux教程,我们讲解了官方计数器的代码实现,react+redux教程(一).我们发现我们没有用到react组件本身的state,而是通过props来导入数据和操作的. 我们知道r ...
- react+redux教程(一)connect、applyMiddleware、thunk、webpackHotMiddleware
今天,我们通过解读官方示例代码(counter)的方式来学习react+redux. 例子 这个例子是官方的例子,计数器程序.前两个按钮是加减,第三个是如果当前数字是奇数则加一,第四个按钮是异步加一( ...
随机推荐
- 第一个shell脚本
打开文本编辑器,新建一个文件,扩展名为sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好. #!/bin/bash echo "Hello World !" &quo ...
- Vue + Webpack + Vue-loader 系列教程(1)功能介绍篇
原文地址:https://lvyongbo.gitbooks.io/vue-loader/content/ Vue-loader 是什么? vue-loader 是一个加载器,能把如下格式的 Vue ...
- EventBus实现activity跟fragment交互数据
最近老是听到技术群里面有人提出需求,activity跟fragment交互数据,或者从一个activity跳转到另外一个activity的fragment,所以我给大家介绍一个开源项目,EventBu ...
- Log4net - 规则简介
参考页面: http://www.yuanjiaocheng.net/CSharp/csharprumenshili.html http://www.yuanjiaocheng.net/entity/ ...
- Autofac - MVC/WebApi中的应用
Autofac前面写了那么多篇, 其实就是为了今天这一篇, Autofac在MVC和WebApi中的应用. 一.目录结构 先看一下我的目录结构吧, 搭了个非常简单的架构, IOC(web), IBLL ...
- continue break 区别
在循环中有两种循环方式 continue , break continue 只是跳出本次循环, 不在继续往下走, 还是开始下一次循环 break 将会跳出整个循环, 此循环将会被终止 count = ...
- 【转】为什么我们都理解错了HTTP中GET与POST的区别
GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二. 最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数. 你可能自己 ...
- [转载]SQL语句中的日期计算
1. 本月的第一天SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0) 2. 本月的最后一天SELECT dateadd(ms,-3,DATEADD( ...
- iOS之计算上次日期距离现在多久, 如 xx 小时前、xx 分钟前等
/** * 计算上次日期距离现在多久 * * @param lastTime 上次日期(需要和格式对应) * @param format1 上次日期格式 * @para ...
- Jquery 获得当前标签的名称和标签属性
得到标签的名称 $("#name").prop("tagName"); 或者 $("#name")[0].tagName; 注意:1.得到的 ...