Skip to content

useSnapshotRef

一个支持快照和防抖的 Ref

Demo

查看代码
tsx
import { ref, defineComponent } from 'vue';
import { useSnapshotRef, type Options } from './index';
import { useToString } from '../../useFunction/useToString/index';
import { sfcButton } from '../../useTsx/useButton/index.tsx';

export default defineComponent({
	setup() {
		// 配置选项
		const delay = ref(500);
		const limit = ref(5);
		const options: Options = {
			limit,
			// include: [],
			exclude: ['a.b', 'a', 'a[Symbol(1)].b'],
			delay
		};
		// 监听对象
		const data = { count: 1 };
		// 导出对象
		const { state, undo, redo, history, canRedo, canUndo } = useSnapshotRef(data, options);

		function todo(num: number) {
			state.value.count += num;
		}

		return () => {
			const domState = () => (
				<div class="row">
					<span>state: </span>
					<span>{useToString(state.value)}</span>
				</div>
			);

			const domDelay = () => {
				const onInput = (e: Event) => {
					delay.value = (e.target as HTMLInputElement).valueAsNumber;
				};
				return (
					<div class="row">
						<input type="range" value={delay.value} onInput={onInput} max={1000} min={0} />
						<span> delay: {delay.value}</span>
					</div>
				);
			};
			const domLimit = () => {
				const onInput = (e: Event) => {
					limit.value = (e.target as HTMLInputElement).valueAsNumber;
				};
				return (
					<div class="row">
						<input type="range" value={limit.value} onInput={onInput} max={10} min={0} />
						<span> limit: {limit.value}</span>
					</div>
				);
			};

			const domOptions = () => (
				<div class="row">
					{sfcButton('count ++', () => todo(1))}
					{sfcButton('count --', () => todo(-1))}
					{sfcButton('redo', redo, !canRedo.value)}
					{sfcButton('undo', undo, !canUndo.value)}
				</div>
			);

			const domHistory = () => (
				<div class="row">
					<span>history (count): </span>
					<span> {history.value.length}</span>
				</div>
			);

			const domHistoryList = () => (
				<div class="row" style="min-height: 200px">
					{history.value.map((item) => {
						return <div>快照: {useToString(item)}</div>;
					})}
				</div>
			);

			return (
				<div class="demo tsx">
					{domState()}
					{domDelay()}
					{domLimit()}
					{domOptions()}
					{domHistory()}
					{domHistoryList()}
				</div>
			);
		};
	}
});

Usage

js
import { useSnapshotRef, type Options } from '@pch1024/vueuse';
const options:Options = {
	limit: 5, 							// 快照最大存储数量
	// include: [], 					// 包含的监听属性路径;","分隔;支持 Symbol 属性
	exclude: ['a,b', 'a,Symbol(1)'], 	// 忽略的监听属性路径;","分隔;支持 Symbol 属性
	delay: 500, 						// 防抖延迟生效时间
};
const data = { count: 1 };
const { state, undo, redo, history, canRedo, canUndo } = useSnapshotRef(data, options);

Type Declarations

查看代码
ts
import type { Ref, ComputedRef, UnwrapRef } from 'vue';

export type Snapshot<T> = {
	snapshot: T;
	datetime: string;
};

export interface Options {
	limit?: Ref<number> | number;
	delay?: Ref<number> | number;
	include?: string[];
	exclude?: string[];
}

export interface ReturnData<T> {
	state: Ref<UnwrapRef<T>>;
	undo: () => void;
	redo: () => void;
	undoList: Ref<Snapshot<T>[]>;
	redoList: Ref<Snapshot<T>[]>;
	history: Ref<Snapshot<T>[]>; // undoList 的别名
	canUndo: ComputedRef<boolean>;
	canRedo: ComputedRef<boolean>;
}

export declare function useSnapshotRef<Raw extends object>(
	raw: Raw,
	options?: Partial<Options>
): ReturnData<Raw>;

Source (建设中)

SourceDemoDocs

Changelog (建设中)