怎么使用react-mile米乐体育

怎么使用react-activation实现keepalive支持返回传参

这篇文章主要介绍“怎么使用react-activation实现keepalive支持返回传参”,在日常操作中,相信很多人在怎么使用react-activation实现keepalive支持返回传参问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么使用react-activation实现keepalive支持返回传参”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

介绍

这个项目是一个商城的后台管理系统,用umi2.0搭建,状态管理使用dva,想要实现类似vue keep-alive的效果。

具体表现为:

从列表页a跳转a的详情页,列表页a缓存

  • 详情页没做任何操作,跳回列表页a,列表页a不刷新,列表页a页码不变

  • 详情页进行了编辑操作,跳回列表页a,列表页a刷新,列表页a页码不变

  • 详情页进行了新建操作,跳回列表页a,列表页a刷新,列表页a页码变为1

从列表页a跳转列表页b,列表页a不缓存

总结就是,一个页面只有跳转指定页面的时候才缓存,并且当返回这个被缓存的页面时,可以控制是否刷新。

代码

1、安装react-activation

"react-activation":"^0.10.2",

2、给路由增加meta

这个项目使用的是集中式配置路由,我增加了meta属性,meta.keepalive存在表示这是一个需要被keepalive的路由,meta.keepalive.topath表示只有当前往这个路由的时候,需要缓存

constroutes=[...{name:'商品管理(商城商品)',path:'/web/supplier/goods/mallgoodsmgr',component:'./supplier/goods/goodsmanage',meta:{keepalive:{topath:'/web/supplier/goods/mallgoodsmgr/detail',//只有去详情页的时候才需要缓存商品管理(商城商品)这个路由},},}...]

3、根组件中渲染

在根组件中,用包裹整个应用,用包裹需要缓存的页面。文档中这部分写在中,如果是umi可以写在layouts里。
通过tree的扁平化计算获取全部的带有meta.keepalive的routes:keepaliveroutes,通过location.pathname判断,如果当前页面是需要keepalive的,那么就需要用包裹。

importkeepalive,{alivescope,usealivecontroller}from'react-activation'//tree扁平化functiontreetolist(tree,childrenkey='routes'){varqueen=[]varout=[]queen=queen.concat(tree)while(queen.length){varfirst=queen.shift()if(first[childrenkey]){queen=queen.concat(first[childrenkey])deletefirst[childrenkey]}out.push(first)}returnout}//从routes路由tree里,拿到所有meta.keepalive的路由:keepaliveroutesconstallflatroutes=treetolist(routes)//所有路由constkeepaliveroutes=allflatroutes.filter((item)=>item.meta?.keepalive)//keepalive的路由functionindex(props){constlocation=uselocation()constrouteitem=keepaliveroutes.find((item)=>item.path==location.pathname)//from页面letdom=props.childrenif(routeitem){dom={props.children}//id一定要加否则keepalive的页面跳转另一个keepalive的页面会有问题}return({dom}
)}

注意alivescope中包含多个keepalive的话,一定要带id。

4、跳转指定页面的时候才缓存

上一步之后,页面虽然被缓存,但是它跳转任何页面都会缓存,我们需要只有跳转指定页面的时候才缓存。
我的方法是

如果跳转的页面正好是它自己的meta.keepalive.topath,那就不做任何操作(因为此时本页面已经被keepalive包裹了,处于缓存的状态)
如果不是它自己的meta.keepalive.topath,调用clear方法,清空缓存

4.1 clear方法

react-activation提供usealivecontroller可以手动控制缓存,其中clear方法用于清空所有缓存中的 keepalive

4.2 用状态管理记录topath

监听history,用状态管理(我用的dva)记录即将前往的页面(下一个页面)topath
我通过dva记录应用即将前往的页面

constglobalmodel={namespace:'global',state:{/***keepalive*/topath:'',keepaliveoptions:{},//给keepalive的页面传的options},effects:{},reducers:{save(state,{payload}){return{...state,...payload,}},settopath(state,{payload}){return{...state,topath:payload,}},},subscriptions:{setup({history,dispatch}){//subscribehistory(url)change,trigger`load`actionifpathnameis`/`history.listen((route,typestr)=>{const{pathname}=routedispatch({type:'settopath',payload:pathname,})})},},}

4.3 给根组件增加useeffect
根组件从dva中读取即将访问的页面topath,然后加一个useeffect,如果即将前往的页面不是当前路由自己的meta.keepalive.topath,就执行react-activation提供的clear方法

...functionindex(props){constlocation=uselocation()consttopath=props.global.topath//从dva中拿到将要访问的页面constrouteitem=keepaliveroutes.find((item)=>item.path==location.pathname)//from页面///新加代码///新加代码///新加代码useeffect(()=>{console.log('topath改变',topath)//from页面是需要keepalive的页面if(routeitem){console.log('from页面是需要keepalive的页面',routeitem)if(topath==routeitem.meta?.keepalive.topath){//所去的页面正好是当前这个路由的keepalive.topathconsole.log('所去的页面正好是当前这个路由的keepalive.topath,不做什么')}else{console.log('clear')if(alivecontroller?.clear){alivecontroller.clear()}}}},[topath])///新加代码endletdom=props.childrenif(routeitem){dom={props.children}//id一定要加否则keepalive的页面跳转另一个keepalive的页面会有问题}return({dom}
)}exportdefaultconnect(({global,login})=>({global,login}))(index)

4.4 优化

现在有一个问题:从列表a跳转详情页,然后跳转列表b,再跳转列表a的时候,a是不刷新的:
列表a => 详情页 => 列表b => 列表a 此时列表a不刷新或者空白。
因为从详情页出来(跳转列表b)的时候,我们没有清空列表a的缓存。
所以要检查当前页面是否是某个需要keepalive页面的topath页面

根组件:

functionindex(){...constparentitem=keepaliveroutes.find((item)=>item.meta?.keepalive?.topath==location.pathname)//parentitem存在表示当前页面是某个keepalive的页面的topathuseeffect(()=>{console.log('topath改变',topath)...///新加代码///新加代码///新加代码//from页面是某个keepalive的页面的topathif(parentitem){console.log('from页面是某个keepalive的页面的topath,parentitem',parentitem)if(topath==parentitem.path){//所去的页面是parentitem.pathconsole.log('所去的页面是parentitem.path,不做什么')}else{console.log('clear')if(alivecontroller?.clear){alivecontroller.clear()}}}},[topath])...}

5、抽离逻辑到自定义hooks

usekeepalivelayout.js

import{useeffect}from'react'import{uselocation}from'react-router-dom'importkeepalive,{alivescope,usealivecontroller}from'react-activation'importroutesfrom'../../config/router.config'//tree扁平化functiontreetolist(tree,childrenkey='routes'){varqueen=[]varout=[]queen=queen.concat(tree)while(queen.length){varfirst=queen.shift()if(first[childrenkey]){queen=queen.concat(first[childrenkey])deletefirst[childrenkey]}out.push(first)}returnout}constallflatroutes=treetolist(routes)//所有路由constkeepaliveroutes=allflatroutes.filter((item)=>item.meta?.keepalive)//keepalive的路由functionindex(props){constlocation=uselocation()//keepaliveconstalivecontroller=usealivecontroller()consttopath=props.global.topath//将要访问的页面constrouteitem=keepaliveroutes.find((item)=>item.path==location.pathname)//from页面constparentitem=keepaliveroutes.find((item)=>item.meta?.keepalive?.topath==location.pathname)useeffect(()=>{console.log('topath改变',topath)//from页面是需要keepalive的页面if(routeitem){console.log('from页面是需要keepalive的页面',routeitem)if(topath==routeitem.meta?.keepalive.topath){//所去的页面正好是当前这个路由的keepalive.topathconsole.log('所去的页面正好是当前这个路由的keepalive.topath,不做什么')}else{console.log('clear')if(alivecontroller?.clear){alivecontroller.clear()}}}//from页面是某个keepalive的页面的topathif(parentitem){console.log('from页面是某个keepalive的页面的topath,parentitem',parentitem)if(topath==parentitem.path){//所去的页面是parentitem.pathconsole.log('所去的页面是parentitem.path,不做什么')}else{console.log('clear')if(alivecontroller?.clear){alivecontroller.clear()}}}},[topath])return{fromisneedkeepalive:routeitem,}}exportdefaultindex

根组件只需要引入这个hooks就可以了:

functionindex(props){constlocation=uselocation()const{fromisneedkeepalive}=usekeepalivelayout(props)//关键代码关键代码关键代码letdom=props.childrenif(fromisneedkeepalive){dom={props.children}//id一定要加否则keepalive的页面跳转另一个keepalive的页面会有问题}return({dom})}

6、 从详情页返回列表页的时候,控制列表页是否刷新,即返回传参

现在只剩下这最后一个问题了,其实就是keepalive的页面,goback传参的问题

思路:

usekeepaliveoptions.js

import{useeffect}from'react'import{usedispatch,usestore}from'dva'import{router}from'umi'/***@descriptionkeepalive的页面,当有参数传过来的时候,可以用这个监听到*@param{(options:object)=>void}func*/exportfunctionusekeepalivepageshow(func){constdispatch=usedispatch()conststore=usestore()conststate=store.getstate()constoptions=state.global.keepaliveoptions??{}useeffect(()=>{func(options)//执行return()=>{console.log('keepalive页面的缓存卸载')dispatch({type:'global/save',payload:{keepaliveoptions:{},},})}},[json.stringify(options)])}/***@descriptionpagea(keepalive的页面)去了pageb,当从pagebgoback,想要给pagea传参的时候,需要使用这个方法*@returns{(params:object)=>void}*/exportfunctionusekeepalivegoback(){constdispatch=usedispatch()functiongoback(parmas={}){dispatch({type:'global/save',payload:{keepaliveoptions:parmas,},})router.goback()}returngoback}

使用:

详情页

import{usekeepalivegoback}from'@/hooks/usekeepaliveoptions'functionindex(){...constkeepalivegoback=usekeepalivegoback()//用于给上一页keepalive的页面传参...return(<>...{keepalivegoback({isaddsuccess:true})//给列表页传options}>...)}

列表页

import{usekeepalivepageshow}from'@/hooks/usekeepaliveoptions'functionindex(){...//options:isaddsuccessiseditsuccessusekeepalivepageshow((options)=>{console.log('keepaliveoptions',options)if(options.isaddsuccess){//新建成功//列表页码变为1并且刷新search()}elseif(options.iseditsuccess){//编辑成功//列表页码不变并且刷新getdata()}})...return<>...}

到此,关于“怎么使用react-activation实现keepalive支持返回传参”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注恰卡编程网网站,小编会继续努力为大家带来更多实用的文章!

展开全文
内容来源于互联网和用户投稿,文章中一旦含有米乐app官网登录的联系方式务必识别真假,本站仅做信息展示不承担任何相关责任,如有侵权或涉及法律问题请联系米乐app官网登录删除

最新文章

网站地图