Jotai?Immer怎么实现undo?redo功能
这篇文章主要介绍了JotaiImmer怎么实现undoredo功能的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JotaiImmer怎么实现undoredo功能文章都会有所收获,下面我们一起来看看吧。
代码不多,直接上了
import{Patch,applyPatches,produceWithPatches}from"immer";import{atomWithImmer}from"jotai-immer";import{atom,createStore}from"jotai/vanilla";import{JSONSchema7}from"json-schema";interfaceHistoryInfo{patch:Patch;inverse:Patch;}interfaceHistoryState{undo:HistoryInfo[];redo:HistoryInfo[];}//业务代码涉及的undo、redo数据exportinterfaceHistoryItem{businessA:{[key:string]:any};businessB:Record<string,JSONSchema7>;businessC:any;}//构建一个undo、redo的数据起点consthistoryItemAtom=atomWithImmer<HistoryItem>({businessA:{},businessB:{},businessC:{},});//触发需要保存的undo的一个操作事件exportconstfireHistoryAtom=atom(0.0);exportconstbusinessAAtom=atomWithImmer<{[key:string]:any}>({});exportconstbusinessBAtom=atomWithImmer<Record<string,JSONSchema7>>({});exportconstbusinessCAtom=atomWithImmer<any>();exportconsthistoryAtom=atomWithImmer<HistoryState>({undo:[],redo:[],});exportconststore=createStore();//页面数据加载完毕写入初始化historyexportconstdataInit=()=>{constnewHis:HistoryItem={businessA:store.get(businessAAtom),businessB:store.get(businessBAtom),businessC:store.get(businessCAtom),};store.set(historyItemAtom,newHis);};//----------------------------------------------------------------//atomsubscriptionsstore.sub(fireHistoryAtom,()=>{constnewHis:HistoryItem={businessA:store.get(businessAAtom),businessB:store.get(businessBAtom),businessC:store.get(businessCAtom),};constoldHis=store.get(historyItemAtom);const[next,patch,inverse]=produceWithPatches(oldHis,(draft)=>{draft=newHis;returndraft;});store.set(historyItemAtom,next);store.set(historyAtom,(draft)=>{draft.undo.push({patch:patch[0],inverse:inverse[0],});draft.redo=[];});});exportconstfireHistory=()=>{setTimeout(()=>{store.set(fireHistoryAtom,Math.random());},20);};//执行业务代码constdoAction=(item:HistoryItem)=>{store.set(businessAAtom,(draft)=>{draft=item.businessA;returndraft;});store.set(businessBAtom,(draft)=>{draft=item.businessB;returndraft;});store.set(businessCAtom,(draft)=>{draft=item.businessC;returndraft;});store.set(historyItemAtom,(draft)=>{draft=item;returndraft;});};exportconstundoAction=()=>{consthistory=store.get(historyAtom);if(history.undo.length===0){return;}constold=history.undo[history.undo.length-1];constcurrentItem=store.get(historyItemAtom);constitem=applyPatches(currentItem,[old.inverse]);doAction(item);store.set(historyAtom,(draft)=>{constcurrent=draft.undo.pop();if(current){draft.redo.push(current);}});};exportconstredoAction=()=>{consthistory=store.get(historyAtom);if(history.redo.length===0){return;}constold=history.redo[history.redo.length-1];constcurrentItem=store.get(historyItemAtom);constitem=applyPatches(currentItem,[old.patch]);doAction(item);store.set(historyAtom,(draft)=>{constcurrent=draft.redo.pop();if(current){draft.undo.push(current);}});};
大致讲下思路
定义 HistoryItem 作为undo、redo所需要恢复的业务数据,可随意扩展。undo、redo本质上就是你点了undo按钮后你的数据需要恢复到上一个状态。当业务复杂了之后,你一次操作可能包含了多个数据的变化,而你undo的操作应该是把这些数据一起还原。所以把涉及到变化的数据都包装在一起,形成一个historyitem。通过 immer提供的produceWithPatches生成撤销和恢复数据, 存在 HistoryState 的undo 里,然后你点击undo按钮,把数据从undo中取出,放入redo中。然后把数据状态通过jotai全局修改,差不多就完成了。
简单的jotai使用是不需要store参与的,这里为了取数据、改数据方便,所以使用了store的监听和set功能。 使用store的代码也很简单,直接在最外层包个provider即可
<Providerstore={mainStore}><MainPage/></Provider>
使用方式应该挺简单的吧。 当你做完需要undo的操作后,调用fireHistory()函数即可。页面的undo、redo按钮可以直接把事件映射到undoAction、redoAction。至于undo、redo按钮是否能点的功能可以直接读取 historyAtom 里面undo、redo的数组长度。
关于“JotaiImmer怎么实现undoredo功能”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“JotaiImmer怎么实现undoredo功能”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注主机评测网行业资讯频道。
上一篇:Go的面向对象编程怎么应用
下一篇:Golang中由零值和gob库特性引起BUG怎么解决
winlogins.exe是什么文件?winlogins.exe是不是病毒
winsock2.6.exe是什么文件?winsock2.6.exe是不是病毒
WinDefendor.dll是什么文件?WinDefendor.dll是不是病毒
系统目录是什么文件?系统目录是不是病毒
wholove.exe是什么文件?wholove.exe是不是病毒
winn.ini是什么文件?winn.ini是不是病毒
w6oou.dll是什么文件?w6oou.dll是不是病毒
winduxzawb.exe是什么文件?winduxzawb.exe是不是病毒
wuammgr32.exe是什么文件?wuammgr32.exe是不是病毒
windiws.exe是什么文件?windiws.exe是不是病毒