From eb581793ae8f04bf2a0f796d588232124c4428d7 Mon Sep 17 00:00:00 2001 From: pei-pay Date: Fri, 3 May 2024 22:20:28 +0900 Subject: [PATCH] wip: useRefHistory --- App.vue | 39 ++++++++++++ index.html | 2 +- main.ts | 6 ++ packages/core/useRefHistory/index.ts | 2 +- packages/ja/starter/useRefHistory.md | 90 +++++++++++++++++++++++++++- starter/useRefHistory.ts | 35 +++++++++++ 6 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 App.vue create mode 100644 main.ts create mode 100644 starter/useRefHistory.ts diff --git a/App.vue b/App.vue new file mode 100644 index 0000000..e794357 --- /dev/null +++ b/App.vue @@ -0,0 +1,39 @@ + + + diff --git a/index.html b/index.html index dcd6967..21dd7a0 100644 --- a/index.html +++ b/index.html @@ -8,6 +8,6 @@
- + diff --git a/main.ts b/main.ts new file mode 100644 index 0000000..b9c93ca --- /dev/null +++ b/main.ts @@ -0,0 +1,6 @@ +import { createApp } from 'vue'; +import App from './App.vue'; + +const app = createApp(App); + +app.mount('#app'); \ No newline at end of file diff --git a/packages/core/useRefHistory/index.ts b/packages/core/useRefHistory/index.ts index fadfe60..6328b4d 100644 --- a/packages/core/useRefHistory/index.ts +++ b/packages/core/useRefHistory/index.ts @@ -5,7 +5,7 @@ import { type UseManualRefHistoryReturn, useManualRefHistory } from '../useManua export interface UseRefHistoryReturn extends UseManualRefHistoryReturn {} -export function useRefHistory(source: Ref) { +export function useRefHistory(source: Ref): UseRefHistoryReturn { const { ignoreUpdates } = watchIgnorable(source, commit) function setSource(source: Ref, value: Raw) { diff --git a/packages/ja/starter/useRefHistory.md b/packages/ja/starter/useRefHistory.md index b6a6d61..095f62d 100644 --- a/packages/ja/starter/useRefHistory.md +++ b/packages/ja/starter/useRefHistory.md @@ -1 +1,89 @@ -# useRefHistory \ No newline at end of file +# useRefHistory + + + +https://vueuse.org/core/useRefHistory/ + +## どういったコンポーザブルか + +ref の変更履歴を自動で追跡し、値を戻したり、戻した値を復活させたりできる関数を提供します。 + +### Demo + +[VueUseの公式サイト](https://vueuse.org/core/useRefHistory/#demo) で実際の動きを確認してみましょう。 + +#### ポイント +- Increment ボタンを押すと count の値が増え、History にその値と時刻が追加される +- Decrement ボタンを押すと count の値を減り、History にその値と時刻が追加される +- Undo ボタンを押すと、count の値が一つ前の値に戻り、History からもその履歴が消える +- Redo ボタンを押すと、Undo で戻した値に戻り、History にもその履歴が復活する + - この時の時刻は redo で戻した時間ではなく、その履歴が最初に追加された時間になっていることに注意! + +## 作り方 + +### ユーザーのインターフェースを考える + +まずはユーザーがこのコンポーザブルをどのように使うか考えてみましょう。デモで確認した通り、カウントの値の変更履歴を管理したいとします。 + +- ユーザーが提供するもの + - 履歴を管理したいref: count +- ユーザーに提供するもの + - 履歴: history + - 値と時刻(タイムスタンプ)がわかるといい + - 履歴を戻す関数: undo + - 戻した履歴を復活させる関数: redo + - 履歴を戻せるかどうかフラグ: canUndo + - 戻したい履歴があるかどうかフラグ: canRedo + +以上のことから下記のような形になれば良さそうです。 + +```ts +const { history, undo, redo, canUndo, canRedo } = useRefHistory(count) +``` + +### 型定義してみる + +ユーザーのインターフェースが決まったので、今度はコンポーザブルの型を考えます。 + +- 履歴(history)は値(snapshot)と時刻(timestamp)のオブジェクトの配列 +- canUndo と canRedo は boolean +- undo と redo は関数 + +```ts +import type { Ref } from 'vue' + +interface UseRefHistoryRecord { + snapshot: T + timestamp: number +} +interface UseRefHistoryReturn { + history: Ref[]> + canUndo: Ref + canRedo: Ref + undo: () => void + redo: () => void +} + +export function useRefHistory(source: Ref): UseRefHistoryReturn { + + // 中身はこれから実装する + + return { + history, + canUndo, + canRedo, + undo, + redo, + } +} +``` + +### 仕様をまとめてみる + +`useRefHistory` がどういったことをするのか実装者の視点で考えてみましょう + +- ユーザーから受け取った値 (引数のsource) を監視し、値が変わったら履歴にその時の値と時刻を追加する +- undo を発火したら、履歴から一番最新のものを削除し、source の値を次に最新の値にする +- redo を発火したら、undo で戻したものの中から一番最近のものを、sourceの値にし、履歴に戻す。 +- canUndo は履歴あればtrue、ないならfalse +- canRedo は undoで戻したものがあれば true、ないなら false \ No newline at end of file diff --git a/starter/useRefHistory.ts b/starter/useRefHistory.ts new file mode 100644 index 0000000..0fe10bb --- /dev/null +++ b/starter/useRefHistory.ts @@ -0,0 +1,35 @@ +import { ref, watch, type Ref } from 'vue' + +interface UseRefHistoryRecord { + snapshot: T + timestamp: number +} +interface UseRefHistoryReturn { + history: Ref[]> + canUndo: Ref + canRedo: Ref + undo: () => void + redo: () => void +} + +export function useRefHistory(source: Ref): UseRefHistoryReturn { + + const history: Ref[]> = ref([]) + const canUndo = ref(false) + const canRedo = ref(false) + const undo = () => {} + const redo = () => {} + + + watch(source, () => { + + }) + + return { + history, + canUndo, + canRedo, + undo, + redo, + } +} \ No newline at end of file