### Vue.js Disorganized Script Setup Example Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/composition-api-code-organization.md Demonstrates a disorganized Vue.js script setup where related state, computed properties, and methods are scattered, making the code harder to understand and maintain. This example highlights the issues addressed by better organization. ```vue ``` -------------------------------- ### Install Playwright and Initialize Project Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-testing-best-practices/reference/testing-e2e-playwright-recommended.md This command installs the Playwright library and its browser binaries, and initializes the project with necessary configuration files like `playwright.config.ts` and example test directories. ```bash npm init playwright@latest ``` -------------------------------- ### Pinia Setup Store: Correctly Returning All State Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-pinia-best-practices/reference/pinia-setup-store-return-all-state.md This example shows the correct implementation of a Pinia setup store where all reactive state properties, getters, and actions are explicitly returned. This ensures proper SSR hydration, visibility in DevTools, and compatibility with Pinia plugins. ```javascript import { defineStore } from 'pinia' import { ref, computed } from 'vue' export const useUserStore = defineStore('user', () => { // All state properties const name = ref('') const email = ref('') const authToken = ref('') const lastFetchTime = ref(null) // Getters const isLoggedIn = computed(() => !!authToken.value) // Actions async function login(credentials) { const response = await fetch('/api/login', { method: 'POST', body: JSON.stringify(credentials) }) const data = await response.json() authToken.value = data.token name.value = data.name email.value = data.email lastFetchTime.value = Date.now() } function logout() { authToken.value = '' name.value = '' email.value = '' } // CORRECT: Return ALL state, getters, and actions return { // State name, email, authToken, lastFetchTime, // Getters isLoggedIn, // Actions login, logout } }) ``` -------------------------------- ### Vue.js: Async Plugin Installation Example Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/plugin-install-before-mount.md This snippet shows how to handle asynchronous operations required for plugin setup in Vue.js before mounting the application. It uses an async function to load necessary data or configurations before installing and mounting. ```typescript import { createApp } from 'vue' import App from './App.vue' import { loadPlugins } from './plugins' async function bootstrap() { const app = createApp(App) // Await async plugin setup const i18nPlugin = await loadI18nMessages() // Install all plugins app.use(i18nPlugin) // Mount after everything is ready app.mount('#app') } bootstrap() ``` -------------------------------- ### Pinia Setup Store: Using Naming Convention for Private State Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-pinia-best-practices/reference/pinia-setup-store-return-all-state.md This example illustrates how to manage 'private' state within a Pinia setup store using a naming convention (e.g., underscore prefix) instead of omitting properties from the return. All state is still returned, but the convention signals its intended internal use, maintaining SSR and DevTools compatibility. ```javascript import { defineStore } from 'pinia' import { ref, computed } from 'vue' export const useUserStore = defineStore('user', () => { // Convention: underscore prefix for "internal" state // Still returned, but signals it's not for external use const _authToken = ref('') const _lastFetchTime = ref(null) // Public state const name = ref('') const email = ref('') const isLoggedIn = computed(() => !!_authToken.value) // Return everything - convention communicates intent return { // "Private" - use with caution _authToken, _lastFetchTime, // Public name, email, isLoggedIn } }) ``` -------------------------------- ### Vue 3: App-Level Provide Example Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/provide-inject-synchronous-setup.md Demonstrates how `app.provide()` can be used to provide values at the application level, which can be called anytime during app initialization, even asynchronously before mounting. ```javascript // main.js import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) // This works - app-level provide app.provide('appConfig', { version: '1.0.0' }) // Even async is OK at app level before mount fetchConfig().then(config => { app.provide('apiConfig', config) app.mount('#app') }) ``` -------------------------------- ### Pinia Options Store: Automatic State Tracking Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-pinia-best-practices/reference/pinia-setup-store-return-all-state.md This example shows a Pinia store defined using the Options API syntax. Unlike setup stores, all state properties declared in the `state` function are automatically tracked and included for SSR, DevTools, and plugins without explicit returning. ```javascript // stores/user.js - Options syntax: all state is tracked automatically import { defineStore } from 'pinia' export const useUserStore = defineStore('user', { state: () => ({ name: '', email: '', authToken: '', // Automatically included lastFetchTime: null // Automatically included }), getters: { isLoggedIn: (state) => !!state.authToken }, actions: { async login(credentials) { // ... } } }) ``` -------------------------------- ### Vue.js: Plugin Installation Order Example Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/plugin-install-before-mount.md This code demonstrates the importance of plugin installation order in Vue.js, especially when plugins have interdependencies. It shows a common pattern where state management and routing plugins are installed before others. ```typescript const app = createApp(App) // 1. State management first (other plugins might need it) app.use(createPinia()) // 2. Router (may depend on state) app.use(router) // 3. Other plugins (may depend on router or state) app.use(authPlugin) app.use(i18nPlugin, { locale: 'en' }) // 4. Mount last app.mount('#app') ``` -------------------------------- ### Expose Native Input Element with Vue 3 Script Setup Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/component-ref-requires-defineexpose.md Shows how to expose native DOM elements or methods to interact with them from a parent component. This example exposes `focus`, `blur` methods and the native input element itself (`el`) from a wrapper component using ` ``` -------------------------------- ### Vue.js Provide/Inject with InjectionKey Example Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-development-guides/references/data-flow-guide.md Shows how to use `provide` and `inject` in Vue.js to avoid prop drilling, along with the best practice of using `InjectionKey` for type safety in TypeScript. ```typescript // keys.ts import type { InjectionKey, Ref } from 'vue' export type Theme = 'light' | 'dark' export const themeKey: InjectionKey> = Symbol('theme') ``` ```vue ``` ```vue ``` -------------------------------- ### Setup Vitest Browser Mode with Playwright Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-testing-best-practices/reference/testing-browser-vs-node-runners.md This command installs the necessary packages for Vitest Browser Mode, including Playwright, which provides the browser automation capabilities. This setup is required for tests that need to interact with a real browser environment. ```bash npm install -D @vitest/browser playwright ``` -------------------------------- ### Vue.js: Duplicate Plugin Installation Protection Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/plugin-install-before-mount.md This example illustrates Vue.js's built-in mechanism for preventing duplicate plugin installations. The `app.use()` method automatically handles duplicate calls, ensuring a plugin is only installed once. ```typescript app.use(myPlugin) app.use(myPlugin) // This second call is ignored - no double installation // This is handled internally by Vue, providing a safety net ``` -------------------------------- ### Vue.js defineEmits Tuple Syntax Example Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-development-guides/references/data-flow-guide.md Illustrates the recommended tuple syntax for `defineEmits` in Vue.js, which provides better type safety for event payloads. ```typescript const emit = defineEmits<{ change: [id: number] // named tuple syntax update: [value: string] }>() ``` -------------------------------- ### Pinia Setup Store: Incorrectly Hidden State Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-pinia-best-practices/reference/pinia-setup-store-return-all-state.md This example demonstrates the incorrect way to define a Pinia setup store by not returning all reactive state properties. This leads to issues with Server-Side Rendering (SSR) hydration, Vue DevTools inspection, and Pinia plugin compatibility as 'private' state remains inaccessible. ```javascript import { defineStore } from 'pinia' import { ref, computed } from 'vue' export const useUserStore = defineStore('user', () => { // Public state const name = ref('') const email = ref('') // "Private" state - NOT returned const authToken = ref('') // Won't be serialized for SSR! const lastFetchTime = ref(null) // Won't appear in DevTools! const isLoggedIn = computed(() => !!authToken.value) async function login(credentials) { const response = await fetch('/api/login', { method: 'POST', body: JSON.stringify(credentials) }) const data = await response.json() authToken.value = data.token // This state won't transfer to client in SSR! name.value = data.name email.value = data.email lastFetchTime.value = Date.now() } // WRONG: Not returning authToken and lastFetchTime return { name, email, isLoggedIn, login } }) ``` -------------------------------- ### Document Provided Values in Provider Components Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/provide-inject-debugging-challenges.md This example shows how to document the values being provided within a Vue component's script setup block. Clear documentation, including the keys and types of provided values, aids other developers in understanding and using the provide/inject API correctly. ```vue ``` -------------------------------- ### Vue.js: Good Practice - Installing Plugins Before Mounting Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/plugin-install-before-mount.md This snippet illustrates the recommended practice of installing all necessary Vue.js plugins using `app.use()` before calling `app.mount()`. This ensures that all dependencies and configurations are available when the application renders, preventing potential issues. ```typescript import { createApp } from 'vue' import App from './App.vue' import router from './router' import { createPinia } from 'pinia' import i18nPlugin from './plugins/i18n' const app = createApp(App) // Install all plugins BEFORE mounting app.use(createPinia()) app.use(router) app.use(i18nPlugin, { locale: 'en' }) // Mount LAST app.mount('#app') ``` -------------------------------- ### Vue Render Function with Composition API (No ``` -------------------------------- ### Pinia Store Usage in Vue Component Setup Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-pinia-best-practices/reference/pinia-no-active-pinia-error.md Illustrates the correct way to use Pinia stores within Vue components, specifically highlighting the difference between ` ``` ```vue ``` ```vue ``` -------------------------------- ### Async in Vue `setup()` Function (Incorrect and Correct) Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/composition-api-script-setup-async-context.md Demonstrates how asynchronous operations behave in Vue's traditional `setup()` function, contrasting incorrect and correct patterns. Unlike ` ``` -------------------------------- ### Vue.js: Clean URL Query Parameter Examples Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-pinia-best-practices/reference/state-url-for-ephemeral-filters.md Demonstrates best practices for constructing URL query parameters in Vue.js applications. The 'GOOD' example shows a clean, readable URL, while the 'AVOID' example illustrates an overly complex and encoded URL. The subsequent example shows how to use defaults to keep URLs minimal. ```javascript // GOOD: Clean, readable URLs /products?category=electronics&sort=price&q=phone // AVOID: Overly complex URLs /products?filters=%7B%22category%22%3A%22electronics%22%7D ``` ```javascript // Use defaults to keep URLs minimal const sort = useRouteQuery('sort', 'newest') // URL shows: /products (when using default sort) // URL shows: /products?sort=price-low (when changed) ``` -------------------------------- ### Vue Setup Execution and Reactivity Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/composition-api-vs-react-hooks-differences.md Explains that the Vue setup function (or ` ``` -------------------------------- ### Map Pinia Setup Store to State, Getters, Actions (Vue.js) Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-pinia-best-practices/reference/pinia-setup-store-return-all-state.md Demonstrates how `ref` becomes state, `computed` becomes getters, and regular functions become actions within a Pinia setup store. It's crucial to return all these elements for proper store functionality. ```javascript defineStore('example', () => { // ref() becomes state const count = ref(0) // → state.count // computed() becomes getters const double = computed(() => count.value * 2) // → getters.double // Regular functions become actions function increment() { // → actions.increment count.value++ } // CRITICAL: Must return all of them return { count, double, increment } }) ``` -------------------------------- ### Vue Component Migration: Options API to Composition API (Vue.js) Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/composition-api-options-api-coexistence.md Illustrates a three-step migration process for a Vue component from a pure Options API to a full Composition API (` ``` -------------------------------- ### Vue.js: Efficient Derived Data with Computed Properties in Templates Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-development-guides/references/reactivity-guide.md Highlights the performance benefits of using `computed()` for expensive operations in Vue.js templates. It contrasts a bad example of using a method that runs on every render with a good example using a computed property that is cached. ```vue ``` -------------------------------- ### Vue 3 ``` -------------------------------- ### Vue.js: Pure Computed Properties vs. Side Effects Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-development-guides/references/reactivity-guide.md Explains the best practice of keeping computed property getters pure in Vue.js, meaning they should not contain side effects. It contrasts a bad example with side effects to a good example where side effects are handled by a separate watcher. ```typescript const count = ref(0) const doubled = computed(() => count.value * 2) watch(count, (value) => { if (value > 10) console.warn('Too big!') }) ``` -------------------------------- ### Testing Async Components with `mountSuspense` Helper (Vue Test Utils) Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-testing-best-practices/reference/testing-suspense-async-components.md Demonstrates how to use the `mountSuspense` helper function to test async components. This approach streamlines the testing process by encapsulating the Suspense wrapper logic. It shows how to pass props and global configurations, and how to assert on the rendered component's content. ```javascript // AsyncUserProfile.test.js import { mountSuspense } from './test-utils' import AsyncUserProfile from './AsyncUserProfile.vue' test('displays user data', async () => { const { component } = await mountSuspense(AsyncUserProfile, { props: { userId: 1 }, global: { stubs: { // Stub any child components if needed } } }) expect(component.find('.username').text()).toBe('John') }) test('handles errors gracefully', async () => { const { component } = await mountSuspense(AsyncUserProfile, { props: { userId: 'invalid' } }) expect(component.find('.error').exists()).toBe(true) }) ``` -------------------------------- ### Vue 3 Script Setup: ref() vs. reactive() Usage Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/sfc-script-setup-reactivity.md Explains the appropriate use cases for `ref()` and `reactive()` in Vue 3's script setup. `ref()` is recommended for primitives and values that might be reassigned, while `reactive()` is suitable for objects and arrays that will be mutated. ```vue ``` -------------------------------- ### Vue.js defineModel for v-model Example Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-development-guides/references/data-flow-guide.md Demonstrates the use of `defineModel` in Vue.js for component `v-model` support. This provides a cleaner way to handle two-way data binding. ```vue ``` -------------------------------- ### Correct Async Patterns in Vue ``` -------------------------------- ### Vue.js: Scrolling to New Item Using nextTick() in ``` -------------------------------- ### Vue Composable Testing with Provide Support (JavaScript) Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-testing-best-practices/reference/testing-composables-helper-wrapper.md A helper function `withSetup` to test Vue composables. It creates a Vue app instance, applies global provides, mounts a component that calls the composable, and returns the composable's result and the app instance. Useful for isolating and testing composable logic with specific dependencies. ```javascript // test-utils.js export function withSetup(composable, options = {}) { let result const app = createApp({ setup() { result = composable() return () => {} } }) // Apply global provides before mounting if (options.provide) { Object.entries(options.provide).forEach(([key, value]) => { app.provide(key, value) }) } app.mount(document.createElement('div')) return [result, app] } // Usage const [result, app] = withSetup(() => useMyComposable(), { provide: { apiClient: mockApiClient, currentUser: { id: 1, name: 'Test User' } } }) ``` -------------------------------- ### Vue 3: Custom Input Wrapper Component Example Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/undeclared-emits-double-firing.md This Vue.js 3 script setup example demonstrates a custom input wrapper component. It correctly declares all re-emitted events ('input', 'change', 'focus', 'blur') using defineEmits to prevent double firing and ensure proper event handling. ```vue ``` -------------------------------- ### Vue 3: Icon Button Wrapper Component Example Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/undeclared-emits-double-firing.md This Vue.js 3 script setup example shows a simple icon button wrapper component. It correctly declares the 'click' event using defineEmits, ensuring that only the component's emitted click event is handled, not any potential native click listeners. ```vue ``` -------------------------------- ### Mount Async Component Correctly with Manual Suspense Wrapper (Vue Test Utils) Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-testing-best-practices/reference/testing-suspense-async-components.md Shows how to correctly test an async component by creating a temporary wrapper component that includes Vue's `` component. This ensures the async setup logic is handled, allowing the component to render and be tested properly. It uses `flushPromises` to wait for the async resolution. ```javascript import { mount, flushPromises } from '@vue/test-utils' import { defineComponent, Suspense } from 'vue' import AsyncUserProfile from './AsyncUserProfile.vue' test('displays user data', async () => { // Create wrapper component with Suspense const TestWrapper = defineComponent({ components: { AsyncUserProfile }, template: ` ` }) const wrapper = mount(TestWrapper) // Initially shows fallback expect(wrapper.text()).toContain('Loading...') // Wait for async setup to complete await flushPromises() // Find the actual component for detailed assertions const profile = wrapper.findComponent(AsyncUserProfile) expect(profile.find('.username').text()).toBe('John') }) ``` -------------------------------- ### Vue 3 Parent Component Template Ref Access (Failing Example) Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/define-expose-before-await.md Illustrates how a parent component attempts to access properties exposed by a child component using template refs. This example demonstrates the failure scenario when the child component incorrectly places `defineExpose` after an `await` statement, resulting in `undefined` properties and runtime errors. ```vue ``` -------------------------------- ### ESLint Configuration for Vue defineEmits Rule Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/defineEmits-must-be-top-level.md Provides an example of how to configure the `vue/valid-define-emits` ESLint rule in `eslint.config.js`. This rule helps enforce the correct usage of `defineEmits` by catching common errors. ```javascript // eslint.config.js export default [ { rules: { 'vue/valid-define-emits': 'error' } } ] ``` -------------------------------- ### Vue.js v-for Range Iteration for Placeholders Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/v-for-range-starts-at-one.md Provides an example of using `v-for` with a number range to render a fixed number of placeholder or skeleton elements, demonstrating a practical use case for this feature. ```html
Loading placeholder {{ n }} of 3...
``` -------------------------------- ### Pinia Store: Setup Style (Composition API - JavaScript) Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-pinia-best-practices/reference/state-use-pinia-for-large-apps.md Defines a Pinia store using the Setup Style, leveraging the Composition API. This style uses `ref` for state and `computed` for derived state, offering a more functional approach. ```javascript import { ref, computed } from 'vue' export const useCounterStore = defineStore('counter', () => { const count = ref(0) const double = computed(() => count.value * 2) function increment() { count.value++ } return { count, double, increment } }) ``` -------------------------------- ### Vue.js Props Down / Events Up Data Flow Example Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-development-guides/references/data-flow-guide.md Demonstrates the 'Props Down / Events Up' principle in Vue.js for one-way data flow. The parent passes data via props, and the child emits events to communicate changes back. ```vue ``` ```vue ``` -------------------------------- ### Vue.js: Cleaning Up Async Effects in Watchers Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-development-guides/references/reactivity-guide.md Provides an example of how to properly clean up asynchronous operations within Vue.js watchers. This is essential for preventing race conditions and unnecessary work, especially with rapid input changes like in search boxes. ```typescript const query = ref('') const results = ref([]) watch(query, async (q, _prev, onCleanup) => { const controller = new AbortController() onCleanup(() => controller.abort()) const res = await fetch(`/api/search?q=${encodeURIComponent(q)}`, { signal: controller.signal, }) results.value = await res.json() }) ``` -------------------------------- ### Create Host Component Wrapper for Complex Vue 3 Composables with `withSetup` Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-testing-best-practices/reference/testing-composables-helper-wrapper.md Provides a utility function `withSetup` to create a host component context for testing complex Vue 3 composables that utilize lifecycle hooks or dependency injection. This function sets up a Vue app instance and mounts it, allowing the composable to execute within a component lifecycle. ```javascript // test-utils.js import { createApp } from 'vue' /** * Helper to test composables that need component context */ export function withSetup(composable) { let result const app = createApp({ setup() { result = composable() // Return a render function to suppress warnings return () => {} } }) app.mount(document.createElement('div')) return [result, app] } ``` -------------------------------- ### Vue 3.5+: Access template refs with useTemplateRef Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-development-guides/references/sfc-guide.md Demonstrates how to access DOM elements or component instances using template refs in Vue 3.5+ with the `useTemplateRef` composable. It shows how to get a ref to an input element and focus it after the component is mounted. ```vue ``` -------------------------------- ### Vue 3 ``` -------------------------------- ### Vue.js Method for List Filtering (Inefficient) Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/v-for-use-computed-for-filtering.md Provides a JavaScript example of a Vue.js method used for filtering a list. This method is inefficient because it gets re-executed on every component re-render, regardless of whether the underlying data has changed. ```javascript // Method recalculates every time component re-renders function getActiveItems() { return items.value.filter(item => item.isActive) } ``` -------------------------------- ### Simple Hash Routing Example (Vue) Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-router-best-practices/reference/router-use-vue-router-for-production.md A basic implementation of client-side routing using hash changes and dynamic components. Suitable for learning, prototypes, or very small applications with limited pages. It relies on manual event listeners and component mapping. ```vue ``` -------------------------------- ### Testing Async Errors with `onErrorCaptured` and Suspense (Vue Test Utils) Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-testing-best-practices/reference/testing-suspense-async-components.md Illustrates how to test error handling within async components using Vue's `onErrorCaptured` hook combined with ``. This example sets up a wrapper that captures errors thrown during the async setup phase, allowing for assertions on the captured error object. It ensures that errors are handled gracefully and tests can verify error states. ```javascript import { mount, flushPromises } from '@vue/test-utils' import { defineComponent, Suspense, h, ref, onErrorCaptured } from 'vue' import AsyncComponent from './AsyncComponent.vue' test('catches async errors', async () => { const capturedError = ref(null) const TestWrapper = defineComponent({ setup() { onErrorCaptured((error) => { capturedError.value = error return true // Prevent error propagation }) return { capturedError } }, render() { return h(Suspense, null, { default: () => h(AsyncComponent, { shouldFail: true }), fallback: () => h('div', 'Loading...') }) } }) const wrapper = mount(TestWrapper) await flushPromises() expect(capturedError.value).toBeTruthy() expect(capturedError.value.message).toContain('Failed to load') }) ``` -------------------------------- ### Vue TransitionGroup with Block Elements (Correct) Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/transition-group-flip-inline-elements.md Provides a correct example of Vue's TransitionGroup using default block-level elements (`
`). This setup ensures that FLIP animations function as expected because block elements support CSS transforms. ```vue ``` -------------------------------- ### Calling Vue.js Composables in Lifecycle Hooks Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/composable-call-location-restrictions.md Shows an example of correctly calling a composable within a lifecycle hook like `onMounted`. This is permissible because the component's execution context is maintained during lifecycle hook execution, allowing for proper hook registration. ```vue ``` -------------------------------- ### Handling Slots with Render Functions in Vue setup() Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-best-practices/reference/rendering-render-function-return-from-setup.md Shows how to correctly render slots when using render functions with Vue's Composition API. The `slots` object provided to `setup()` must be called within the returned render function to ensure slot content is rendered appropriately. ```javascript import { h, ref } from 'vue' export default { setup(props, { slots }) { const count = ref(0) return () => h('div', [ h('p', `Count: ${count.value}`), // Slots must also be called inside the render function slots.default?.() ]) } } ``` -------------------------------- ### Correct Pinia and Router Plugin Order in Vue.js Source: https://github.com/vuejs-ai/skills/blob/main/skills/vue-pinia-best-practices/reference/pinia-no-active-pinia-error.md Ensures Pinia is installed before the router to prevent errors when router guards access Pinia stores. This is crucial for applications using both Pinia for state management and Vue Router for navigation. ```javascript // main.js - WRONG ORDER import { createApp } from 'vue' import { createPinia } from 'pinia' import router from './router' // Router uses a store in navigation guard import App from './App.vue' const app = createApp(App) // WRONG: Router is installed first, but its guards use stores app.use(router) // Router guard calls useAuthStore() - FAILS! app.use(createPinia()) app.mount('#app') ``` ```javascript // main.js - CORRECT ORDER import { createApp } from 'vue' import { createPinia } from 'pinia' import router from './router' import App from './App.vue' const app = createApp(App) // CORRECT: Pinia installed before anything that uses stores app.use(createPinia()) app.use(router) // Now router guards can safely use stores app.mount('#app') ```