内容简介:距离上篇文章已经过去了大半个月,本来打算只更新代码,最后还是决定把做的过程中遇到的问题记录出来,说不定就可以帮助一些同学,也算是幸事,如果没有,那就当作自己梳理知识点吧!该篇文章主要讲述以下知识点:有三种方式:
距离上篇文章已经过去了大半个月,本来打算只更新代码,最后还是决定把做的过程中遇到的问题记录出来,说不定就可以帮助一些同学,也算是幸事,如果没有,那就当作自己梳理知识点吧!
该篇文章主要讲述以下知识点:
- 如何mock数据
- React组件中修改Redux中的数据
mock数据
有三种方式:
- 利用node搭服务,mock数据
- 利用现成网上mock服务,比如 easy mock
- 本地json数据模拟请求
介绍下本地数据模拟请求,利用axios请求数据:
import axios from 'axios'; const BaseUrl='./mock/homeData/'; const getHome=()=>{ return axios.get(BaseUrl+'home.json').then(res=>{ return res.data }) } const getArticleList=()=>{ return axios.get(BaseUrl+'articleList.json').then(res=>{ return res.data }) } export { getHome,getArticleList }
本地json数据存放位置如下
React组件中修改Redux中的数据
定义好state,reducer
//userReducer.js // 1.定义默认数据 let initialState = { userId:'', userName:'',//实际项目与此不同 userImage: '', userDesc:'' } // action creators export const actions = { login: (userInfo) => { return {type: 'CHANGE_USER',userName: userInfo.username,userId:userInfo.userId} }, logout:()=>{ return {type:'LOGOUT'} } }; // 2.Reducer const userReducer = (state = initialState, action) => { switch (action.type) { case 'CHANGE_USERIMAGE': return { ...state, userImage: action.userImage } case 'CHANGE_USERID': return { ...state,userId:action.userId} case 'CHANGE_USER': return { ...state,userName:action.userName,userId:action.userId} case 'LOGOUT': return {...state,userName:'',userId:''} default: return state } } // 3.导出 export default userReducer;
在组件中操作修改state
... this.props.login({username:username,userId:userId});//修改存储在redux中的用户信息 ... const mapStateToProps = (state, ownProps) => { return { } } const mapDispatchToProps = (dispatch, ownProps) => { return bindActionCreators({ login: authActions.login },dispatch); } Login=connect(mapStateToProps,mapDispatchToProps)(Login) export default Login;
Redux通过reducer解析action。reducer是一个普通的js函数,接受action作为参数,然后返回一个新的state。
三大原则
- 唯一数据源
- 保持state状态只读
- state的改变必须通过纯函数完成
Redux
Redux应用只维护一个全局的状态对象,存在Redux的store中。程序任何时候都不能直接去修改状态state,如果需要修改state,必须发送一个action,通过action去描述如何修改state。action描述了改变state的意图,真正对state作出修改的是reducer。reducer必须是 纯函数 ,所以reducer在收到action后,不能直接去修改原来的状态state,而是应该创建一个新的状态对象返回。
纯函数需要满足两个条件:
(1)对于同样的参数值,函数返回结果总是相同的,就是函数结果不依赖任何在程序执行过程中可能改变的变量。
(2)函数的执行过程不会产生比的副作用,例如会修改外部对象,有时会去修改页面标题,这就是副作用。
数据流向的一个简单示意图,来自Flux官网
可以看出Redux应用的主要组成有action,reducer和store。
action
action是Redux中的信息载体,是store的唯一来源。把action发给store必须通过store中的dispach方法。其实action就是一个普通的js对象,但是每个action必须有一个type属性用来描述action类型,要做什么操作。除了type属性歪,action的结构完全由你决定,不过应该保证可以清晰描述使用场景。
function logout(info){ return { type:'LOGOUT', info } }
reducer
reducer根据action做出响应,决定如何修改应用状态state。其实在写reducer之前就应该设计好state。
state:
// 1.定义默认数据 let initialState = { userId:'', userName:'',//实际项目与此不同 userImage: '', userDesc:'' }
reducer:
// 2.Reducer const userReducer = (state = initialState, action) => { switch (action.type) { case 'CHANGE_USERIMAGE': return { ...state, userImage: action.userImage } case 'CHANGE_USERID': return { ...state,userId:action.userId} case 'CHANGE_USER': return { ...state,userName:action.userName,userId:action.userId} case 'LOGOUT': return {...state,userName:'',userId:''} default: return state } }
这里使用了ES6的扩展运算符(…)创建新的state对象,避免直接修改之前的state对象。
在实际项目中,可能会有很多reducer,就需要把reducer拆分保存在单独的文件中。Redux提供了一个combineReducers函数,用来合并reducer。
import {combineReducers} from 'redux'; import pageHeaderReducer from './pageHeader.js'; import userReducer from './userReducer'; const appReducer = combineReducers({ pageHeaderReducer, userReducer, }); export default appReducer;
store
store是Redux中的一个对象,作为action和reducer之间的一个桥梁。
作用:
- 保存应用状态
- 通过方法获取应用状态
- 通过dispatch(action)发送更新状态的指令
- 通过方法subscribe(listener)注册监听函数、监听状态的改变。
总结下Redux中的数据流过程:
- (1)通过调用store.dispatch(action)。一个action描述了“发生了什么”的对象以及可能会携带一些参数。store.dispatch(action)可以在应用中任何位置调用。
- (2)Redux的store调用reducer函数。store传递两个参数给reducer,分别是当前应用的状态和action,reducer必须是纯函数。
- (3)根reducer可以把多个子reducer合并在一起,返回组成最终的应用状态。利用combineReducers进行组合。
- (4)Redux的store保存根reducer返回的完整应用状态,这整个流程走完,应用状态才完成更新。
在React中使用Redux
基础安装使用方法已经在第一篇中做了介绍,此处重点介绍下connect中的mapStateToProps和mapDispatchToProps。
mapStateToProps
mapStateToProps是一个函数,从名字上看,该函数作用就是把state转换成props。state就是Redux store中保存的应用状态,会作为参数传递给mapStateToProps,props就是被连接展示组件的props。
const mapStateToProps = (state) => { return { userName:state.userReducer.userName, userImage:state.userReducer.userImage, userId:state.userReducer.userId } }
当store中的state改变后,mapStateToProps就会重新执行,重新计算传递给展示组件的props,从而触发组件的重新渲染。
注意:store中的state改变一定会导致mapStateToProps重新执行,但却不一定会触发组件渲染render方法重新执行。如果mapStateToProps新返回的对象和之前的对象浅比较相等,组件的shouldComponentUpdate方法就会返回false,组件的render方法就不会被再次触发,这也是一个重要优化吧!
mapDispatchToProps
mapDispatchToProps接收store.dispatch方法作为参数,返回展示组件用来修改state的函数。
const mapDispatchToProps = (dispatch, ownProps) => { return { getOrder: (data) => dispatch(actionCreator(data)) } }
另外一种写法,利用bindActionCreators
import { bindActionCreators } from "redux"; const mapDispatchToProps = (dispatch, ownProps) => { return bindActionCreators({ getOrder: actionCreator.getOrder },dispatch); }
bindActionCreators作用是将单个或多个ActionCreator转化为dispatch(action)的函数集合形式。个人感觉会内部自动注入dispatch,不用我们手动去dispatch。之后通过connect连接即可
const mapStateToProps = (state, ownProps) => { return { } } const mapDispatchToProps = (dispatch, ownProps) => { return bindActionCreators({ login: authActions.login },dispatch); } Login=connect(mapStateToProps,mapDispatchToProps)(Login)
注意connect函数参数必须第一个为mapStateToProps,第二个必须为mapDispatchToProps,可以不写mapDispatchToProps,但是如果需要mapDispatchToProps却不能不写mapStateToProps,否则会报错,个人第一次使用就犯了这个错误:sweat:
啰哩啰嗦的说了这么多,码字不易,点赞再走哈。完整项目代码在 github ,欢迎点个star,不胜感激:clap::clap::clap:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。