内容简介:一些小型项目,只使用 React 完全够用了,数据管理使用props、state即可,那什么时候需要引入Redux呢? 当渲染一个组件的数据是通过props从父组件中获取时,通常情况下是A –> B,但随着业务复杂度的增加,有可能是这样的:A –> B –> C –> D –> E,E需要的数据需要从A那里通过props传递过来,以及对应的E –> A逆向传递callback。组件BCD是不需要这些数据的,但是又必须经由它们来传递,这样不太友好,而且传递的props以及callback对BCD组件的复用也会
为什么用Redux
一些小型项目,只使用 React 完全够用了,数据管理使用props、state即可,那什么时候需要引入Redux呢? 当渲染一个组件的数据是通过props从父组件中获取时,通常情况下是A –> B,但随着业务复杂度的增加,有可能是这样的:A –> B –> C –> D –> E,E需要的数据需要从A那里通过props传递过来,以及对应的E –> A逆向传递callback。组件BCD是不需要这些数据的,但是又必须经由它们来传递,这样不太友好,而且传递的props以及callback对BCD组件的复用也会造成影响。或者兄弟组件之间想要共享某些数据,也不是很方便传递、获取等。诸如此类的情况,就有必要引入Redux`了。
注:其实 A --> B --> C --> D --> E 这种情况,React不使用props层层传递也是能拿到数据的,使用Context即可。
Redux 的三大基本原则
redux的核心概念就是store、action、reducer
约法三章
State 是只读的 react文档中说惟一改变 state 的方法就是触发 action,奇怪的是 我们说State是只读的,但是为啥现在又说可以修改了呢,其实我们并不是直接修改state,action”是用来向 store 表示要修改 state 的载体。所以我们并没有直接设置state的方法,使用了dispatch(action) 发送 action 至 store 是唯一改变 state 的方式
store
- UI唯一数据来源;
- 维持应用的 state;
- 提供 getState() 方法获取 state;
- 提供 dispatch(action) 方法更新 state;
- 通过 subscribe(listener) 注册监听器; 通过 subscribe(listener) 返回的函数注销监听器。
action
必须拥有type属性,用来描述发生什么,action通过reducer处理生成newState后才能够更改store信息。但是为了更好的语义编程,Redux通过语句store.dispatch(action)来更新store,reducer对action的处理在内部处理。
reducer
仅仅只是根据action.type处理一下需要更新的state
创建目录
创建Store模块 数据源
//store/index.js
/*引入createStore 是用来创建一个数据源对象保存我们的数据的*/
import { createStore, applyMiddleware, compose } from 'redux';
import { createLogger } from 'redux-logger';
//引用数据源
// store是引用的reducer
// action会触发reducer
import allreducers from './reducers/index';
//数据处理后会返回给数据源 才能取到最新的数据 在根组件index里获取
const logger = createLogger();
const store = createStore(
allreducers,
applyMiddleware(logger)
)
console.log(store)
function listerner () {
store.getState();
}
store.subscribe(listerner);
export default store;复制代码
传入Store
Store保存了整个应用的单一状态树,所有容器组件都需要从store中读取,我们可以store作为属性传递给每个组件,子组件通过props获取,但是如果嵌套过深,写起来会很麻烦。还好,react-redux提供一个叫provider的组件,他可以让所有组件都可以访问到store(他的实现原理实际上是利用了react的context功能),而不必显示的一层层传递了。
import { Provider } from 'react-redux'
import store from './store';
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
{routes }
</BrowserRouter>
</Provider>,
document.getElementById('app')
);复制代码
创建Reducer 处理业务数据
//reducers/index.js
import * as Types from 'src/store/constants'
import { combineReducers } from 'redux';
const initState = {
isLogin: "未登录",
themecolor: "red",
count: 0
}
const loginReducer = (state = initState.isLogin ,action) => {
switch (action.type) {
case Types.LOGIN_TYPE:
return state = action.isLogin
default:
return state
}
}
const themeReducer = (state = initState.themecolor ,action) => {
switch (action.type) {
case Types.THEME_TYPE:
return state = action.themecolor
default:
return state
}
}
const counterReducer = (state = initState.count, action) => {
switch(action.type) {
case Types.ADD_TYPE: return state + 1;
default: return state;
}
}
export default combineReducers({
isLogin:loginReducer,
themecolor:themeReducer,
count:counterReducer
})复制代码
注意:combineReducers() 函数的作用是把多个 reducer 合并成一个最终的 reducer 函数。
常量统一保存
//constants/index.js
/*常量统一保存,便于管理*/ export const LOGIN_TYPE = "LOGIN_TYPE" export const THEME_TYPE = "THEME_TYPE" export const ADD_TYPE = "ADD_TYPE"复制代码
创建Action模块
actions/index.js
import * as Types from 'src/store/constants'
export const loginAction = function(isLogin) {
return {
type: Types.LOGIN_TYPE,
isLogin
}
}
export const themeAction = function(themecolor) {
return {
type: Types.THEME_TYPE,
themecolor
}
}
export const addAction = () => {
return {
type: Types.ADD_TYPE
}
}复制代码
组件调用
import React, {PureComponent} from "react"
import store from 'src/store'
import { loginAction,themeAction,addAction } from 'src/store/actions'
const counterfn = () => {
document.getElementById("counter").innerHTML = store.getState().count
}
store.subscribe(counterfn);
class NwdLogin extends React.Component {
constructor(props){
super(props)
}
componentDidMount() {
}
render () {
var state = store.getState();
return (
<div>
<div id="counter"></div>
<div>
<button onClick={() => store.dispatch(addAction())}>add </button>
</div>
</div>
)
}
}
export default NwdLogin复制代码
、
注意:在不使用react-redux的情况下 必须使用store.subscribe(listener), store更新后回调listener,回调函数里面可以调用store.getStore()来获取更新后得state哟~
结合 react-redux使用
react-redux,redux和react的桥梁工具。 react-redux将组建分成了两大类,UI组建component和容器组件container。
UI组件:
- 只负责 UI 的呈现,
- 不带有任何业务逻辑 没有状态(即不使用this.state这个变量)
- 所有数据都由参数(this.props)提供 不
- 使用任何 Redux 的 AP
容器组件:
- 负责管理数据和业务逻辑,不负责 UI 的呈现
- 带有内部状态
- 使用 Redux 的 API
1)通过connect方法将React组件和Redux连接起来,react-redux 中引入了 connect
import React, {PureComponent} from "react"
import { connect } from 'react-redux'
import { loginAction,themeAction,addAction } from 'src/store/actions'
class NwdLogin extends React.Component {
constructor(props){
super(props)
}
componentDidMount() {
}
render () {
console.log(this.props)
return (
<div>
{this.props.isLogin}
<button onClick={() => this.props.loginAction("已登录")}>设置登录状态</button>
<button style={{backgroundColor:this.props.themecolor}} onClick={() => this.props.themeAction("#fff")}>设置themecolor状态{this.props.themecolor}</button>
</div>
)
}
}
const mapStateToProps = (state,ownProps) => {
return {
isLogin: state.isLogin,
themecolor: state.themecolor
}
}
const mapDispatchToProps = ((dispatch,ownPorps) => {
return {
loginAction: (isLogin) => dispatch({
type: "LOGIN_TYPE",
isLogin: isLogin
}),
themeAction: (themecolor) => dispatch({
type: "THEME_TYPE",
themecolor: themecolor
})
}
})
export default connect(mapStateToProps,mapDispatchToProps)(NwdLogin)复制代码
1)connect()() 其实这儿是两次函数调用。首先。connect() 返回了一个函数,然后我们立刻调用了这个函数并给它传递进第二个括号内的参数。第二个参数一般是一个 React 组件这是一种常见的“函数式编程”的写法。
2)connect() 的第一个参数是个返回了一个对象的函数 mapStateToProps,这个对象的属性将会变成 React 组件中的“props”的属性,你可以看到他们的值来自 store 的 state。这里我把这第一个参数命名为“mapStateToProps”,如命名所示,是希望它来将全局 states 转化成本地 component 的 props。 mapStateToProps() 将会接收到一个携带着完整的 Redux store 的参数 store,然后抽出本地组件需要的 states 转换成 props。
3)
如果不写mapDispatchToProps,只能自己手动调用this.props.dispatch()
import React, {PureComponent} from "react"
import { connect } from 'react-redux'
import { loginAction,themeAction,addAction } from 'src/store/actions'
class NwdLogin extends React.Component {
constructor(props){
super(props)
}
componentDidMount() {
}
render () {
console.log(this.props)
return (
<div>
{this.props.isLogin}
<button onClick={() => this.props.dispatch(loginAction("已登录"))}>设置登录状态</button>
<button style={{backgroundColor:this.props.themecolor}} onClick={() => this.props.dispatch(themeAction("#fff"))}>设置themecolor状态{this.props.themecolor}</button>
</div>
)
}
}
const mapStateToProps = (state,ownProps) => {
return {
isLogin: state.isLogin,
themecolor: state.themecolor
}
}
/*const mapDispatchToProps = ((dispatch,ownPorps) => {
return {
loginAction: (isLogin) => dispatch({
type: "LOGIN_TYPE",
isLogin: isLogin
}),
themeAction: (themecolor) => dispatch({
type: "THEME_TYPE",
themecolor: themecolor
})
}
})*/
export default connect(mapStateToProps)(NwdLogin)复制代码
react-redux中connect的装饰器用法@connect
import React, {PureComponent} from "react"
import { connect } from 'react-redux'
import { loginAction,themeAction,addAction } from 'src/store/actions'
@connect(
state => {
return {
isLogin: state.isLogin,
themecolor: state.themecolor
}
},
{
loginAction,
themeAction,
addAction
}
)
class NwdLogin extends React.Component {
constructor(props){
super(props)
}
componentDidMount() {
}
render () {
console.log(this.props)
return (
<div>
{this.props.isLogin}
<button onClick={() => this.props.loginAction("已登录")}>设置登录状态</button>
<button style={{backgroundColor:this.props.themecolor}} onClick={() => this.props.themeAction("#fff")}>设置themecolor状态{this.props.themecolor}</button>
</div>
)
}
}
export default NwdLogin
复制代码
redux的bindActionCreators
bindActionCreators是redux的一个API,作用是将单个或多个ActionCreator转化为dispatch(action)的函数集合形式。 开发者不用再手动dispatch(actionCreator(type)),而是可以直接调用方法。
import React, {PureComponent} from "react"
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { loginAction,themeAction,addAction } from 'src/store/actions'
@connect(
state => {
return {
isLogin: state.isLogin,
themecolor: state.themecolor
}
},
dispatch => bindActionCreators({loginAction,themeAction,addAction},dispatch)
)
class NwdLogin extends React.Component {
constructor(props){
super(props)
}
componentDidMount() {
}
render () {
console.log(this.props)
return (
<div>
{this.props.isLogin}
<button onClick={() => this.props.loginAction("已登录")}>设置登录状态</button>
<button style={{backgroundColor:this.props.themecolor}} onClick={() => this.props.themeAction("#fff")}>设置themecolor状态{this.props.themecolor}</button>
</div>
)
}
}
export default NwdLogin
复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
XML Hacks
Michael Fitzgerald / O'Reilly Media, Inc. / 2004-07-27 / USD 24.95
Developers and system administrators alike are uncovering the true power of XML, the Extensible Markup Language that enables data to be sent over the Internet from one computer platform to another or ......一起来看看 《XML Hacks》 这本书的介绍吧!