web-utilities-vueuse
Vue 3でWebサイトやアプリを作る際に、ブラウザ情報、センサー、ネットワーク状況、状態管理、アニメーション、コンポーネントなど、様々な機能を簡単に利用できるようにする便利なツール集を提供するSkill。
📜 元の英語説明(参考)
VueUse composable utility collection for Vue 3 - browser, sensor, network, state, animation, and component utilities
🇯🇵 日本人クリエイター向け解説
Vue 3でWebサイトやアプリを作る際に、ブラウザ情報、センサー、ネットワーク状況、状態管理、アニメーション、コンポーネントなど、様々な機能を簡単に利用できるようにする便利なツール集を提供するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o web-utilities-vueuse.zip https://jpskill.com/download/10326.zip && unzip -o web-utilities-vueuse.zip && rm web-utilities-vueuse.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10326.zip -OutFile "$d\web-utilities-vueuse.zip"; Expand-Archive "$d\web-utilities-vueuse.zip" -DestinationPath $d -Force; ri "$d\web-utilities-vueuse.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
web-utilities-vueuse.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
web-utilities-vueuseフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
VueUse Composable パターン
クイックガイド: VueUse は、ブラウザ API、センサー、ネットワーク、状態、およびコンポーネントロジックをリアクティブな composable にラップする、Vue 3 用の 250 以上の composable 関数を提供します。ツリーシェイキングのために、
@vueuse/coreから個々の関数をインポートしてください。すべての composable はリアクティブな ref を返し、Vue Composition API の規約に従います。永続的な状態にはuseLocalStorage、リアクティブな HTTP にはuseFetch、可視性検出にはuseIntersectionObserver、共有状態にはcreateGlobalState、双方向バインディングヘルパーにはuseVModelを使用します。常に<script setup>またはsetup()内で composable を同期的に呼び出してください。クリーンアップは Vue のライフサイクルを通じて自動的に行われます。
<critical_requirements>
重要: この Skill を使用する前に
すべてのコードは
CLAUDE.mdのプロジェクト規約に従う必要があります (kebab-case、名前付きエクスポート、インポート順序、import type、名前付き定数)
(必ず <script setup> または setup() の中で VueUse composable を同期的に呼び出してください -- 非同期コールバック、setTimeout、または条件ブロックの中では絶対に呼び出さないでください)
(VueUse composable で大きなオブジェクト/配列を使用する場合は、深いリアクティビティのオーバーヘッドを避けるために、ref の代わりに shallowRef を必ず使用してください)
(必ず typeof window !== "undefined" をチェックするか、VueUse の組み込みの SSR セーフな composable を使用して SSR を処理してください -- ブラウザ API はサーバーレンダリング中にクラッシュします)
*(必ず @vueuse/core から個々の composable をインポートしてください -- ツリーシェイキングを無効にする `import as vueuse` は絶対に使用しないでください)**
</critical_requirements>
自動検出: VueUse, vueuse, @vueuse/core, @vueuse/integrations, useLocalStorage, useSessionStorage, useClipboard, useFetch, useMouse, useScroll, useIntersectionObserver, useResizeObserver, useElementVisibility, useMediaQuery, usePreferredDark, useDark, useToggle, useCounter, useCycleList, useWebSocket, useEventSource, useEventListener, useTransition, useRafFn, createGlobalState, useRefHistory, syncRef, useVModel, useVirtualList, onClickOutside, onKeyStroke, createFetch
使用する場面:
- リアクティブなラッパーによるブラウザ API へのアクセス (localStorage, clipboard, media queries)
- リアクティブな ref としてのセンサーデータ (マウス位置、スクロール、リサイズ、交差)
- 中止、再フェッチ、インターセプターを備えたリアクティブな HTTP リクエスト
- 状態管理ライブラリなしでコンポーネント間で共有されるグローバル状態
- コンポーネントユーティリティ (v-model ヘルパー、仮想リスト、キーボードショートカット)
- SSR セーフなブラウザ API へのアクセス
使用しない場面:
- アクション/ミューテーションを伴う複雑な状態管理 (専用の状態ソリューションを使用してください)
- キャッシュ/無効化を伴うサーバーサイドのデータフェッチ (データフェッチソリューションを使用してください)
- リアクティビティを必要としない単純なワンオフ操作
- Vue 以外のプロジェクト (VueUse は Vue 3 のリアクティビティシステムに依存します)
カバーされる主要なパターン:
- コアユーティリティ (
useToggle,useCounter,useCycleList) - ブラウザ composable (
useLocalStorage,useClipboard,useMediaQuery,useEventListener) - センサー composable (
useMouse,useScroll,useIntersectionObserver,useResizeObserver) - ネットワーク composable (
useFetch,useWebSocket,useEventSource) - 状態 composable (
createGlobalState,useRefHistory,syncRef) - コンポーネント composable (
useVModel,useVirtualList,onClickOutside,onKeyStroke) - アニメーション composable (
useTransition,useRafFn)
詳細なリソース:
- examples/core.md - コアユーティリティ、ブラウザ API、イベントリスナー
- examples/sensors.md - マウス、スクロール、交差、リサイズ、可視性
- examples/network.md - useFetch, useWebSocket, useEventSource
- examples/state.md - createGlobalState, useRefHistory, syncRef, 永続化
- examples/component.md - useVModel, useVirtualList, onClickOutside, onKeyStroke
- reference.md - Composable 決定フレームワーク、SSR ガイド、落とし穴
<philosophy>
Philosophy
VueUse は Composition API composable パターン に従います: リアクティブなロジックを、ref とメソッドを返す再利用可能な関数にカプセル化します。各 composable は、単一の関心事 (ブラウザ API、センサー、またはユーティリティ) をラップし、Vue のライフサイクルを通じて自動的にセットアップ/破棄を処理します。
主要な原則: VueUse composable はツリーシェイキングのために設計されています。使用するものだけをインポートしてください -- 各関数は最小限のオーバーヘッドで個別にインポートできます。
import { useLocalStorage, useDark, useMediaQuery } from "@vueuse/core";
// リアクティブな localStorage -- タブ間で同期
const userName = useLocalStorage("user-name", "Guest");
// 自動検出によるダークモード
const isDark = useDark();
// レスポンシブブレークポイント
const MOBILE_BREAKPOINT = "(max-width: 768px)";
const isMobile = useMediaQuery(MOBILE_BREAKPOINT);
VueUse を使用する場面
- ブラウザ API をリアクティビティでラップする (localStorage, clipboard, geolocation)
- DOM の状態をリアクティブに追跡する (スクロール位置、要素の可視性、マウス)
- フルストアのセットアップなしで軽量なグローバル状態を実現する
- コンポーネントユーティリティ (キーボードショートカット、クリック外、仮想リスト)
- 単純なケース向けのリアクティブなデータフェッチ
VueUse を使用しない場面
- キャッシュ、無効化、楽観的アップデートを伴う複雑なサーバー状態 (データフェッチソリューションを使用してください)
- 算出された派生と開発ツールを伴う複雑なクライアント状態 (専用の状態ソリューションを使用してください)
- Vue 以外のプロジェクト (リアクティビティシステムは Vue 固有です)
- リアクティビティなしでネイティブブラウザ API で十分な場合
現在のバージョン
VueUse v14.x は現在の安定版リリースであり、Vue 3.5 以降をサポートしています。すべての composable は TypeScript で記述されており、完全な型推論が可能です。
</philosophy>
<patterns>
コアパターン
パターン 1: リアクティブストレージ (useLocalStorage, useSessionStorage)
ブラウザストレージとタブ間で同期する永続的なリアクティブ状態。
<script setup lang="ts">
import { useLocalStorage, useSessionStorage } from "@vueuse/core";
interface UserPreferences {
theme: "light" | "dark";
fontSize: number;
sidebarCollapsed: boolean;
}
const DEFAULT_PREFERENCES: UserPreference
(原文がここで切り詰められています) 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
VueUse Composable Patterns
Quick Guide: VueUse provides 250+ composable functions for Vue 3 that wrap browser APIs, sensors, network, state, and component logic into reactive composables. Import individual functions from
@vueuse/corefor tree-shaking. All composables return reactive refs and follow Vue Composition API conventions. UseuseLocalStoragefor persistent state,useFetchfor reactive HTTP,useIntersectionObserverfor visibility detection,createGlobalStatefor shared state, anduseVModelfor two-way binding helpers. Always call composables in<script setup>orsetup()synchronously. Clean up is automatic via Vue's lifecycle.
<critical_requirements>
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST call VueUse composables synchronously inside <script setup> or setup() -- NEVER inside async callbacks, setTimeout, or conditional blocks)
(You MUST use shallowRef instead of ref for large objects/arrays in VueUse composables to avoid deep reactivity overhead)
(You MUST handle SSR by checking typeof window !== "undefined" or using VueUse's built-in SSR-safe composables -- browser APIs crash during server rendering)
*(You MUST import individual composables from @vueuse/core -- NEVER use `import as vueuse` which defeats tree-shaking)**
</critical_requirements>
Auto-detection: VueUse, vueuse, @vueuse/core, @vueuse/integrations, useLocalStorage, useSessionStorage, useClipboard, useFetch, useMouse, useScroll, useIntersectionObserver, useResizeObserver, useElementVisibility, useMediaQuery, usePreferredDark, useDark, useToggle, useCounter, useCycleList, useWebSocket, useEventSource, useEventListener, useTransition, useRafFn, createGlobalState, useRefHistory, syncRef, useVModel, useVirtualList, onClickOutside, onKeyStroke, createFetch
When to use:
- Browser API access with reactive wrappers (localStorage, clipboard, media queries)
- Sensor data as reactive refs (mouse position, scroll, resize, intersection)
- Reactive HTTP requests with abort, refetch, and interceptors
- Global state shared across components without a state management library
- Component utilities (v-model helpers, virtual lists, keyboard shortcuts)
- SSR-safe browser API access
When NOT to use:
- Complex state management with actions/mutations (use a dedicated state solution)
- Server-side data fetching with caching/invalidation (use your data-fetching solution)
- Simple one-off operations that don't need reactivity
- Non-Vue projects (VueUse depends on Vue 3's reactivity system)
Key patterns covered:
- Core utilities (
useToggle,useCounter,useCycleList) - Browser composables (
useLocalStorage,useClipboard,useMediaQuery,useEventListener) - Sensor composables (
useMouse,useScroll,useIntersectionObserver,useResizeObserver) - Network composables (
useFetch,useWebSocket,useEventSource) - State composables (
createGlobalState,useRefHistory,syncRef) - Component composables (
useVModel,useVirtualList,onClickOutside,onKeyStroke) - Animation composables (
useTransition,useRafFn)
Detailed Resources:
- examples/core.md - Core utilities, browser APIs, event listeners
- examples/sensors.md - Mouse, scroll, intersection, resize, visibility
- examples/network.md - useFetch, useWebSocket, useEventSource
- examples/state.md - createGlobalState, useRefHistory, syncRef, persistence
- examples/component.md - useVModel, useVirtualList, onClickOutside, onKeyStroke
- reference.md - Composable decision framework, SSR guide, gotchas
<philosophy>
Philosophy
VueUse follows the Composition API composable pattern: encapsulate reactive logic in reusable functions that return refs and methods. Each composable wraps a single concern (a browser API, sensor, or utility) and handles setup/teardown automatically via Vue's lifecycle.
Key principle: VueUse composables are designed for tree-shaking. Import only what you use -- each function is independently importable with minimal overhead.
import { useLocalStorage, useDark, useMediaQuery } from "@vueuse/core";
// Reactive localStorage -- syncs across tabs
const userName = useLocalStorage("user-name", "Guest");
// Dark mode with auto-detection
const isDark = useDark();
// Responsive breakpoint
const MOBILE_BREAKPOINT = "(max-width: 768px)";
const isMobile = useMediaQuery(MOBILE_BREAKPOINT);
When to Use VueUse
- Wrapping browser APIs with reactivity (localStorage, clipboard, geolocation)
- Tracking DOM state reactively (scroll position, element visibility, mouse)
- Lightweight global state without full store setup
- Component utilities (keyboard shortcuts, click outside, virtual lists)
- Reactive data fetching for simple cases
When NOT to Use VueUse
- Complex server state with caching, invalidation, optimistic updates (use your data-fetching solution)
- Complex client state with computed derivations and devtools (use a dedicated state solution)
- Non-Vue projects (the reactivity system is Vue-specific)
- When native browser API is sufficient without reactivity
Current Version
VueUse v14.x is the current stable release, supporting Vue 3.5+. All composables are written in TypeScript with full type inference.
</philosophy>
<patterns>
Core Patterns
Pattern 1: Reactive Storage (useLocalStorage, useSessionStorage)
Persistent reactive state that syncs with browser storage and across tabs.
<script setup lang="ts">
import { useLocalStorage, useSessionStorage } from "@vueuse/core";
interface UserPreferences {
theme: "light" | "dark";
fontSize: number;
sidebarCollapsed: boolean;
}
const DEFAULT_PREFERENCES: UserPreferences = {
theme: "light",
fontSize: 14,
sidebarCollapsed: false,
};
// ✅ Good Example - Typed reactive localStorage
const preferences = useLocalStorage<UserPreferences>(
"user-prefs",
DEFAULT_PREFERENCES,
);
// Read and write like a normal ref
preferences.value.theme = "dark"; // auto-persists to localStorage
// Session-only storage (cleared on tab close)
const sessionToken = useSessionStorage("session-token", "");
// Remove from storage
preferences.value = null; // removes the key from localStorage
</script>
Why good: automatic serialization/deserialization, cross-tab sync via storage events, typed with generics, cleanup is automatic
// ❌ Bad Example - Manual localStorage
const prefs = ref(JSON.parse(localStorage.getItem("user-prefs") ?? "null"));
watch(
prefs,
(val) => {
localStorage.setItem("user-prefs", JSON.stringify(val)); // manual sync
},
{ deep: true },
);
// No cross-tab sync, no automatic cleanup, error-prone serialization
Why bad: manual serialization is error-prone, no cross-tab sync, no SSR safety, deep watcher on every change is expensive
Pattern 2: Event Listeners (useEventListener)
Auto-cleaned event listeners with type safety.
<script setup lang="ts">
import { useEventListener } from "@vueuse/core";
import { useTemplateRef } from "vue";
const buttonRef = useTemplateRef("button");
// ✅ Good Example - Auto-cleanup event listeners
// Automatically removed when component unmounts
useEventListener(window, "resize", () => {
console.log("Window resized:", window.innerWidth);
});
// Works with template refs -- waits for mount
useEventListener(buttonRef, "click", (event) => {
console.log("Button clicked:", event);
});
// Multiple events on same target
useEventListener(document, "visibilitychange", () => {
console.log("Visibility:", document.visibilityState);
});
</script>
Why good: automatic cleanup on unmount prevents memory leaks, handles ref lifecycle (waits for mount), type-safe event names
// ❌ Bad Example - Manual event listener
onMounted(() => {
window.addEventListener("resize", handleResize);
});
onUnmounted(() => {
window.removeEventListener("resize", handleResize); // easy to forget!
});
Why bad: manual add/remove is error-prone -- missing onUnmounted cleanup causes memory leaks
Pattern 3: Media Queries and Dark Mode
Reactive responsive design and theme management.
<script setup lang="ts">
import {
useMediaQuery,
usePreferredDark,
useDark,
useToggle,
} from "@vueuse/core";
// ✅ Good Example - Reactive breakpoints
const MOBILE_BREAKPOINT = "(max-width: 768px)";
const TABLET_BREAKPOINT = "(min-width: 769px) and (max-width: 1024px)";
const isMobile = useMediaQuery(MOBILE_BREAKPOINT);
const isTablet = useMediaQuery(TABLET_BREAKPOINT);
// System preference detection
const prefersDark = usePreferredDark();
// Full dark mode with toggle (adds class to html element)
const isDark = useDark();
const toggleDark = useToggle(isDark);
</script>
<template>
<nav :class="{ 'nav--compact': isMobile }">
<button @click="toggleDark()">
{{ isDark ? "Light Mode" : "Dark Mode" }}
</button>
</nav>
</template>
Why good: reactive media queries update the ref automatically on resize, useDark handles class toggling and persistence, useToggle provides a clean toggle function
Pattern 4: Clipboard Access
Reactive clipboard API with permission handling.
<script setup lang="ts">
import { useClipboard } from "@vueuse/core";
// ✅ Good Example - Clipboard with feedback
const source = ref("Text to copy");
const { text, copy, copied, isSupported } = useClipboard({ source });
async function handleCopy(): Promise<void> {
await copy(); // copies source.value to clipboard
// `copied` ref is true for 1.5s (default) after copy
}
</script>
<template>
<div v-if="isSupported">
<button @click="handleCopy">
{{ copied ? "Copied!" : "Copy" }}
</button>
</div>
<div v-else>Clipboard API not supported</div>
</template>
Why good: isSupported check for graceful degradation, copied provides automatic feedback timing, source reactive binding
Pattern 5: Core Utilities (useToggle, useCounter, useCycleList)
Simple reactive utilities for common state patterns.
<script setup lang="ts">
import { useToggle, useCounter, useCycleList } from "@vueuse/core";
// ✅ Good Example - Toggle state
const [isOpen, toggleOpen] = useToggle(false);
// Counter with bounds
const MIN_COUNT = 0;
const MAX_COUNT = 100;
const { count, inc, dec, reset } = useCounter(0, {
min: MIN_COUNT,
max: MAX_COUNT,
});
// Cycle through options
const themes = ["light", "dark", "auto"] as const;
const {
state: currentTheme,
next: nextTheme,
prev: prevTheme,
} = useCycleList([...themes]);
</script>
<template>
<div>
<button @click="toggleOpen()">{{ isOpen ? "Close" : "Open" }}</button>
<div>
<button @click="dec()">-</button>
<span>{{ count }}</span>
<button @click="inc()">+</button>
</div>
<button @click="nextTheme()">Theme: {{ currentTheme }}</button>
</div>
</template>
Why good: eliminates boilerplate for common patterns, useCounter enforces min/max bounds, useCycleList handles wrapping automatically
Pattern 6: useFetch for Reactive HTTP
Reactive data fetching with abort, refetch, and interceptors.
<script setup lang="ts">
import { useFetch } from "@vueuse/core";
import { computed } from "vue";
const userId = ref(1);
const apiUrl = computed(() => `/api/users/${userId.value}`);
// ✅ Good Example - Reactive fetch with auto-refetch
const { data, isFetching, error, abort } = useFetch(apiUrl, {
refetch: true, // re-fetches when apiUrl changes
}).json<User>();
// Manual fetch with immediate: false
const { data: submitResult, execute } = useFetch("/api/submit", {
immediate: false,
})
.post(formData)
.json();
async function handleSubmit(): Promise<void> {
await execute(); // manually trigger the fetch
}
</script>
Why good: URL reactivity triggers automatic refetch, .json<T>() provides type-safe parsing, abort for cancellation, immediate: false for manual control
See examples/network.md for createFetch, interceptors, and advanced patterns.
Pattern 7: createGlobalState for Shared State
Lightweight global state without a state management library.
// stores/counter.ts
import { createGlobalState } from "@vueuse/core";
import { computed, shallowRef } from "vue";
// ✅ Good Example - Global state with computed
export const useGlobalCounter = createGlobalState(() => {
const count = shallowRef(0);
const doubleCount = computed(() => count.value * 2);
const isPositive = computed(() => count.value > 0);
function increment(): void {
count.value++;
}
function decrement(): void {
count.value--;
}
function reset(): void {
count.value = 0;
}
return { count, doubleCount, isPositive, increment, decrement, reset };
});
<!-- Any component can use the shared state -->
<script setup lang="ts">
import { useGlobalCounter } from "@/stores/counter";
const { count, doubleCount, increment, decrement } = useGlobalCounter();
</script>
Why good: shared state across components, no provider/inject boilerplate, composable pattern with computed derivations, shallowRef for performance
</patterns>
<red_flags>
RED FLAGS
High Priority:
- Calling composables inside
asyncfunctions,setTimeout, or event handlers -- composables must be called synchronously insetup()to bind to the component lifecycle - Using
refinstead ofshallowReffor large objects in storage composables -- causes unnecessary deep reactivity tracking on every nested property - Accessing browser APIs without SSR guards --
useLocalStorage,useClipboard,useMousecrash during server-side rendering
Medium Priority:
- Using
import * from "@vueuse/core"-- defeats tree-shaking, imports the entire 250+ function library - Not using
isSupportedcheck from composables that wrap browser APIs -- causes runtime errors in unsupported environments - Creating custom composables for functionality VueUse already provides -- check the docs first
- Using
watch+refto track DOM state that VueUse composables handle reactively (useMouse,useScroll, etc.)
Gotchas & Edge Cases:
useLocalStoragereturns aRemovableRef-- setting.value = nullremoves the key from storage entirely, not storingnulluseFetchwithrefetch: truefires immediately AND on URL change -- useimmediate: falseif you only want manual controlcreateGlobalStatecreates a singleton per import -- state persists until page reload, even after all components unmountuseIntersectionObservercallback fires immediately with current state on creation -- don't assume first callback means element just became visibleuseDarkmodifies thehtmlelement's class -- ensure your CSS expects the class name it adds (default:dark)useWebSocketauto-reconnects by default -- passautoReconnect: falseif you want manual controluseEventListenerwith a template ref waits foronMountedinternally -- the listener is NOT active duringsetup()useRefHistorytracks every change by default -- use{ deep: false }for shallow tracking oruseManualRefHistoryfor explicit snapshots
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
All code must follow project conventions in CLAUDE.md
(You MUST call VueUse composables synchronously inside <script setup> or setup() -- NEVER inside async callbacks, setTimeout, or conditional blocks)
(You MUST use shallowRef instead of ref for large objects/arrays in VueUse composables to avoid deep reactivity overhead)
(You MUST handle SSR by checking typeof window !== "undefined" or using VueUse's built-in SSR-safe composables -- browser APIs crash during server rendering)
*(You MUST import individual composables from @vueuse/core -- NEVER use `import as vueuse` which defeats tree-shaking)**
Failure to follow these rules will cause SSR crashes, performance degradation, and lifecycle errors.
</critical_reminders>