当我们在多个页面中使用到了相同的属性时就可以用到状态管理器,将这些状态存到外部的一个单独的文件中,不管在什么时候想使用都可以很方便的获取。
react和vue有些不同,react没有自己专属的状态管理方式。它使用的其实是js相关的状态管理器。我们需要记住的是,视图可以引起状态的改变,而状态的改变会导致视图的二次渲染。
说了这么半天,那么我们在react中到底是怎样使用状态管理器的呢?
redux的前身技术是flux,他和flux很相像,但是又不完全相同。两者都规定将模型的更新逻辑全部集中在一个层面中(flux之中的store,redux之中的reducer);但是redux中没有dispatcher的概念,他依赖的是纯函数来做事件处理器;并且redux不回去修改你的数据,它会返回一个新的对象用于更新state状态。
首先我们先校园电影推荐来认识一下redux中的一些属性
1、store:
保存数据/状态的地方,可以把它看成是一个容器。记得在整个应用之中只能有一个store
import { createstore } from 'redux'const store = createstore(fn)
2、state:
可以把state看成是store的实例对象,他包含了状态管理器中所有的状态,是某个时间点所有数据/状态的集合
const state = store.getstate()
3、action
redux中最重要的属性之一,唯一修改store种状态的方式就是提交一个action;action是一个对象,具有type属性,通常这个type属性作为提交的关键key值
const action = { type: 'add_todo', payload: 'learc redux' //这里的payload是作为参数传入的,可以不写}
4、store.dispatch():
提交action的唯一方式,我们就是通过这种方式将action提交到状态管理器,不管后期使用了什么其他的状态管理其工具,最终都归结与这里。
store.dispatch({ type: 'add_todo'})
5、reducer:
store在收到action之后,必须返回一个新的state,这样view才会发生变化,而这个state的计算过程就叫做reducer
reducer是一个函数,他接受当前的state和action,返回一个全新的state
const reducer = (state = { count: 10 //给state中的属性设置初始值,因为状态管理器在每次刷新后都会清空,我们可以从本地获取上次存储的值作为初始值}, action) => { switch (action.type) { ca 'reduce': // 这里可以看到我们根据action的type值作为key值进行查找,当dispatch的时候,就可以根据这些key值的判断查找到要执行的操作 return { ...state, count: state.count - action.payload } //我们根据action的需要,在原有的state基础上,返回了一个新的state对象,没有修改原来的state ca 'add': return { ...state, count: state.count + action.payload } default: return state; }} export default reducer
可以看到我们返回新的state对象的方式是通过es6中的 … 语法,这种方式看起来是不是有点复杂,有点点low?那么我们介绍一种新的方式,首先引入immutable组件
这种方式其实是js实现了一种深拷贝,将原来的state对象深拷贝了一份,这样对新的state对象做出任何修改都不会影响到原来的state,是不是特别香!!!
yarn add immutable -s
使用方式:
import { map } from 'immutable' //引入map函数const ur = (state = map({ //使用map深拷贝了state islogin: localstorage.getitem('islogin') === 'true', token: localstorage.getitem('token') || '', adminname: localstorage.getitem('adminname') || '', role: localstorage.getitem('role') * 1 || 1}), action) => { switch (action.type) { ca 'change_login_state': return state.t('islogin', action.payload) //t方式写入 ca 'change_token': return state.t('token', action.payload) ca 'change_admin_name': return state.t('adminname', action.payload) ca 'change_role': return state.t('role', action.payload) default: return state }}export default ur
state => { return { adminname: state.getin(['ur', 'adminname']), // get方式获取值, 参数是这种形式 //第一个参数的含义: ur状态管理器中的 //第二个参数含义: 名为adminname的状态/属性 }}
6、设计状态管理器
首先根据模块化开发的思想,我们可以在一个项目中设计多个种类状态管理器,最后合并到一个里面;例如,商品的状态,用户信息的状态….
import { createstore, combinereducers } from "redux";// 这个combinereducers方法就是模块化开发的关键,它帮助我们把所有分模块的状态管理器合并到一起import pro from './modules/pro'import app from './modules/app' const reducer = combinereducers({ //把分模块创建的所有reducer都集中到这里的r天津外国语学院educer pro, app}) const store = createstore(reducer) export default store
我们要知道一件事,当我们在某一个时间点希望获取状态或者修改状态的时候,状态管理器store会为我们生成一个state实例对象,我们可以对这个实例对象进行操作。state的变化会引起view视图的改变,但是因为用户们接触不到state,只能接触到view,所以state的变化必然也必须是由view引起的!!!而action其实就是view 发出的一个通知,当用户修改了view的时候,就会发出这个通知,告诉程序,state需要发生改变了。
//我们可以这样理解,dispatch,action,store三者的关系可以看成是邮局,邮件,收信人
//我们想寄一封信(action),告诉朋友(收信人),我们找到工作了,需要通过邮局(dispatch)的帮助;当邮局帮我们把邮件送到了收件人的地方时,收件人就获取到了我要传递的信息,也会做出响应的改变
//我们在调用dispatch的时候,通过type(key值)找到对应的邮件送到store
// 可以通过provider和connect在组件中对状态管理器进行‘链接',链接成功之后就可以使用状态管理器中的状态和方法了 // /src/xxx/index.jsximport {connect} from 'react-redux' function app (props) { ...}export default connet(mapstatetoprops, mapdispatchtoprops)(app) // /index.jsimport {provider} from 'react-redux'import app from './app.jsx'import store './store/index.js' reactdom.render ( <react.strictmode> <provider store = { store }> <app /> </provider> </react.strickmode>) //也可以使用到装饰器的高阶函数 @connect @withrouter //以往从状态树取出对应的数据,让后通过props传给组件使用通过react-redux自带的connect()方法class home extends react.component { //....}export default connect(state => ({todos: state.todos}))(home); //使用装饰器的话就变成这样,好像没那么复杂@connect(state => ({ todos: state.todos }))class home extends react.component { //....}
这里我们对这种方式做出讲解:
我们要链接状态管理器,首先在整个项目的入口文件index.js中引入状态store,通过provider的方式将store作为参数传递给子组件,有点类似于祖先组件给后代组件传值的方式
其次,我们要在使用状态管理器的组件中通过connect这一个高阶函数进行连接,该高阶函数的原理是,传入函数作为参数,返回另一个函数
mapstatetoprops:
从名字可以看出,是把state中的状态遍历处理,放到props中,我们就可以在函数式组件中的props参数值里面获取到state.
mapdispatchtoprops:
将状态管理器中的提交方法存入到props中,这样我们就可以在组件中对状态管理器中的状态进行修改。
const app = (props) => { // 组件中直接就可以通过props访问到状态管理器中的状态 props.adminname props.count props.bannerlist props.reducefn ...}export default connect( // 可以看到这里就是传入两个函数,返回两个函数 state => { return { adminname: state.getin(['ur', 'adminname']), //这是一种存储状态的方式,一会会讲到 count: state.app.count, //参数是s新闻英文tate,我们把app状态管理器中的count属性传递到props中的count bannerlist: state.pro.bannerlist, } }, dispatch => { return { reducefn () { //我们在这里定义了一个reducefn,里面是dispatch的方法,我们在props中就可以通过reducefn这个方法发送'reduce'提交的信息 dispatch({ type: 'reduce', payload: 5 //payload为参数,可以不传 }) } } })(app)
我们除了可以使用这种基本的方式修改状态意外,还可以使用一些工具
redux-thunk、redux-saga
//在store.js之中把thunk引入并挂载到状态管理器中 import { createstore, combinereducers, applymiddleware} from 'redux' import thunk from 'redux-thunk'import app from './modules/app'import pro from './modules/pro' const reducer = combinereducers({ app, pro})// 通过applymiddleware将thunk挂载到状态管理器const store = createstore(reducer, applymiddleware(thunk)) export default store
然后我们单独设计一个文件用来封装修改状态的方式,包含异步方式
// .../store/actioncreator/pro.js // 这个文件就是专门用来触发异步操作// thunk模块执行的时候, actioncreator 函数有默认的参数为dispatch// 该dispatch 可以用来触发reducer// 有时候在触发异步的时候, 需要传递参数,这个时候,可以在函数内部返回一个 actioncreator 函数const actions = { getbannerlistaction (dispatch) { fetch('http://121.89.205.189/api/banner/list') .then(res => res.json()) .then(res => { dispatch({ type: 'change_banner_list', payload: res.data }) }) }, getprolistaction (count) { //有参数,返回一个函数,函数参数默认为dispatch count = count || 1 return function (dispatch) { fetch('http://121.89.205.189/api/pro/list?count=' + count) .then(res => res.json()) .then(res => { dispatch({ type: 'change_pro_list', payload: res.data }) }) } }} export default actions
可以把上面的步骤看成定义了一个action的对象,里面有一些提交action的dispatch,当我们要在组件中要修改状态时,可以直接在这个对象中使用函数,函数会自动发起请求,提交action。
在下面组件中的使用也可以看出来,我们dispatch(actions.getbannerlistaction);其实就是提交aciton的形式,只不过我们把action修改和异步请求封装起来了
import actions from './store/actioncreator/pro'const app = (props) => { // props之中可以直接访问到 props.reducefn() props.addfn() props.getbannerlist() props.getprolist()} const mapstatetoprops = (state) => { return { count: state.app.count, bannerlist: state.pro.bannerlist, prolist: state.pro.prolist }} const mapdispatchtoprops = (dispatch) => { return { reducefn () { //通过正常方式修改状态 dispatch({ type: 'reduce', payload: 5 }) }, addfn () { dispatch({ type: 'add', payload: 5 }) }, getbannerlist () { //通过thunk方式修改状态 dispatch(actions.getbannerlistaction) }, getprolist () { dispatch(actions.getprolistaction(2)) } }} export default connect(mapstatetoprops, mapdispatchtoprops)(app)
链接的方式和普通的react-redux一模一样,最后也是通过dispatch一个action的方式修改状态
安装redux-saga
yarn add redux-saga immutable redux-immutable -s
可以把redux-saga和redux-thunk看作是一种发送dispatch的方式,在旧时代我们送信(dispatch)是通过汽车、步行;使用工具可以看成是通过动车,飞机发送信件
import { createstore, combinereducers, applymiddleware } from 'redux' import cr汉朝历史事件eatesagamiddleware from 'redux-saga' import mysaga from './mysaga' //异步操作说明 import home from './modules/home'import app from './modules/app' const reducer = combinereducers({ app, home}) const sagamiddleware = createsagamiddleware() //生成saga中间件 const store = createstore(reducer, applymiddleware(sagamiddleware))//建立链接//和thunk一样,把saga中间件挂载到状态管理器中就可以使用saga的方式修改状态了 sagamiddleware.run(mysaga)//run: 发送// 这里是封装了一个mysage函数作为修改状态的函数 export default store
在redux-saga中,修改状态时使用genarator函数实现的
import { call, put, takelatest } from 'redux-saga/effects' import { getbannerlist, getprolist } from '../api/home' // redux-saga ---> 必须与generator函数一起使用 function * getbannerlistaction() { const res = yield call(getbannerlist) //call--调用函数 yield put({ type: 'change_banner_list', payload: res.data })}function * getprolistaction (action){ const res = yield call(getprolist, action.payload) yield put({ type: 'change_pro_list', payload: res.data })} function * mysaga () { yield takelatest('request_banner_list', getbannerlistaction) yield takelatest('request_pro_list', getprolistaction)} export default mysaga
如果看不懂上面,别怕。看这里
// mysaga文件中我们定义了发送的方式import { takelatest } from 'redux-saga/effects'// takelatest ---分配任务;在下方。我们自己定义了key并为其分配了事件,这些事件就是store.dispatch零基础想学英语()函数使用的 function * getprolistaction (action){ const res = yield call(getprolist, action.payload) yield put({ type: 'change_pro_list', payload: res.data })}function * mysaga () { yield takelatest('request_pro_list', getprolistaction)} // 我们以后再想修改状态的时候就不需要使用store.dispatch()这样修改了// 可以使用这个文件中定义的key值进行修改 // 我们在组件的connect中这样定义自定义函数,直接根据key值调用这里的修改方法dispatch => { dispatch({ type: 'request_pro_list'})} // put, call// call ---> 含义是调用// put ---> 含义是推,把当前的action推到下一个去执行(队列)。 yield put(action)yield call(fn)
以上就是本人结合各种文档对于react常用的状态管理器的一些理解,如果有说错的地方,还希望大家能指出,我们共同进步。
除了以上这些状态管理器,市面上还有一些工具,mobx,umi,dva,这些有时间的话本人也会整理出来与大家共享。
到此这篇关于对于react各种状态管理器的解读的文章就介绍到这了,更多相关react状态管理器内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!
本文发布于:2023-04-04 02:17:39,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/72735fade22c57adcaf73f2d00acb2f6.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:React各种状态管理器的解读及使用方法.doc
本文 PDF 下载地址:React各种状态管理器的解读及使用方法.pdf
留言与评论(共有 0 条评论) |