VueUse useRefHistory 历史快照

VueUse useRefHistory 可以自动跟踪响应式对象的历史更改,还提供撤消和重做功能。

与其他History区别

名称说明
useDebouncedRefHistory防抖、连续触发的事件,只在最后执行一次记录
useThrottledRefHistory限流、一段时间内只执行一次记录
useManualRefHistory需要手动提交记录

代码示例

import { ref } from 'vue';
import { useRefHistory } from '@vueuse/core';

const times = ref(0);
const { history, undo, redo, canUndo, canRedo,clear ,commit  } = useRefHistory(times);
//撤销操作
undo();
//重置
redo();
//是否允许撤回
let isAllow=canUndo;
//是否允许重置
let isAllow=canRedo;
//清除全部历史记录
clear();
//手动提交记录
commit();

在线例子

例子

跟踪Objects/arrays

当跟踪的是Objects/arrays对象或数组你需要设置deep:true

// 需要记录的ref对象
const userInfo = ref({num:100,name:'文一路'});
// deep 深化拷贝, 
const { history, undo, redo, canUndo, canRedo } = useRefHistory(userInfo, 
{
   clone: true
 });
//修改对象数据
userInfo.value.num=userInfo.value.num+1;

自定义clone函数

使用 js原生的 structuredClone进行深拷贝:

import { useRefHistory } from '@vueuse/core'

const refHistory = useRefHistory(target, { clone: structuredClone })

或者使用 lodash的cloneDeep函数进行深拷贝:

import { cloneDeep } from 'lodash-es'
import { useRefHistory } from '@vueuse/core'

const refHistory = useRefHistory(target, { clone: cloneDeep })

或者lightweight klona:

import { klona } from 'klona'
import { useRefHistory } from '@vueuse/core'

const refHistory = useRefHistory(target, { clone: klona })

自定义Dump/Parse

如果不使用clone参数,您可以传递自定义函数来控制序列化和解析函数

import { useRefHistory } from '@vueuse/core'

const refHistory = useRefHistory(target, {
  dump: JSON.stringify,
  parse: JSON.parse,
})

记录快照数量

//最多记录15条历史快照
const refHistory = useRefHistory(target, {
  capacity: 15, 
})
//清除全部快照
refHistory.clear();

刷新时间

 // 'pre'(默认) , 'post' and 'sync'
const refHistory = useRefHistory(target, {
  flush: 'sync',
})

默认值是'pre',以使其与Vue的watchers的默认值保持一致,如果需要在同一个“tick”中创建多个历史点,可以手动使用commit()

const num = ref(0)
const { history, commit } = useRefHistory(num)

num.value = 1
commit()

num.value = 2
commit()

console.log(history.value);
//因为手动commit了 所以一次tick多了2个快照
/* [
  { snapshot: 2 },
  { snapshot: 1 },
  { snapshot: 0 },
] */

同步刷新sync,当跟踪的对象被修改后会立即产生快照,但你可以使用batch(fn)将多个同步操作生成单个历史快照

const item = ref({ names: [], version: 1 })
const { history, batch } = useRefHistory(item, { flush: 'sync' })

batch(() => {
 //第一次修改
 item.names.push('Lena');
 //第二次修改
 item.version++;
})

console.log(history.value)
/* [
  { snapshot: { names: [ 'Lena' ], version: 2 },
  { snapshot: { names: [], version: 1 },
] */

如果使用{flush: 'sync', deep: true},批处理在对数组的操作也很有用。Splice最多可以生成三个原子操作,这些操作将被推送到ref历史记录中。

const arr = ref([1, 2, 3])
const { history, batch } = useRefHistory(r, { deep: true, flush: 'sync' })

batch(() => {
  arr.value.splice(1, 1) // batch ensures only one history point is generated
})