内容简介:一些小型项目,只使用 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 复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python网络编程(第3版)
[美] Brandon Rhodes、[美] John Goerzen / 诸豪文 / 人民邮电出版社 / 2016-9 / 79.00元
本书针对想要深入理解使用Python来解决网络相关问题或是构建网络应用程序的技术人员,结合实例讲解了网络协议、网络数据及错误、电子邮件、服务器架构和HTTP及Web应用程序等经典话题。具体内容包括:全面介绍Python3中最新提供的SSL支持,异步I/O循环的编写,用Flask框架在Python代码中配置URL,跨站脚本以及跨站请求伪造攻击网站的原理及保护方法,等等。一起来看看 《Python网络编程(第3版)》 这本书的介绍吧!