All skills
hyf0 avatar

/vue-options-api-best-practices

@bc922e4 official
by hyf0hyf0/vue-skills2.9k stars
167

Vue 3 Options API style (data(), methods, this context). Each reference shows Options API solution only.

Use this Skill: https://skilld.dev/gh/hyf0/vue-skills/vue-options-api-best-practices

This session only. Nothing lands on disk.

referencets-options-api-type-event-handlers.md

≈1.4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Explicitly Type Event Handlers in Options API Methods

Impact: MEDIUM - Without explicit type annotations, event handler parameters in Options API methods are typed as any. This defeats TypeScript's purpose, causing noImplicitAny errors in strict mode and losing type safety for DOM event properties.

Task Checklist

  • Always add type annotations to event handler method parameters
  • Use the correct DOM event type (Event, MouseEvent, KeyboardEvent, etc.)
  • Use type assertions for event.target when accessing element-specific properties
  • Enable strict: true in tsconfig.json to catch implicit any errors

The Problem

import { defineComponent } from 'vue'

export default defineComponent({
  methods: {
    // BAD - 'event' is implicitly 'any'
    handleClick(event) {
      console.log(event.target.value)  // No type checking!
    },

    // BAD - Causes error with noImplicitAny
    handleInput(event) {
      // Error: Parameter 'event' implicitly has an 'any' type
      this.searchTerm = event.target.value
    }
  }
})

The Solution: Explicit Event Types

import { defineComponent } from 'vue'

export default defineComponent({
  data() {
    return {
      searchTerm: ''
    }
  },
  methods: {
    // GOOD - Explicit Event type
    handleClick(event: MouseEvent) {
      console.log(event.clientX, event.clientY)
      // Cast target for element-specific properties
      const button = event.target as HTMLButtonElement
      console.log(button.disabled)
    },

    // GOOD - Explicit Event type with target assertion
    handleInput(event: Event) {
      const input = event.target as HTMLInputElement
      this.searchTerm = input.value
    },

    // GOOD - KeyboardEvent for keyboard handlers
    handleKeydown(event: KeyboardEvent) {
      if (event.key === 'Enter') {
        this.submit()
      }
    }
  }
})

Common DOM Event Types

Event Type Use For
Event Generic events, custom events
MouseEvent click, dblclick, mouseenter, mouseleave, etc.
KeyboardEvent keydown, keyup, keypress
InputEvent input (modern browsers)
FocusEvent focus, blur
SubmitEvent form submit
DragEvent drag, drop, dragenter, dragover
TouchEvent touchstart, touchend, touchmove
WheelEvent wheel

Type Assertions for event.target

event.target is typed as EventTarget | null, which is too generic. Use type assertions:

methods: {
  // Input element
  onInputChange(event: Event) {
    const target = event.target as HTMLInputElement
    console.log(target.value)
    console.log(target.checked)  // for checkboxes
  },

  // Select element
  onSelectChange(event: Event) {
    const target = event.target as HTMLSelectElement
    console.log(target.value)
    console.log(target.selectedIndex)
  },

  // Form element
  onFormSubmit(event: SubmitEvent) {
    event.preventDefault()
    const form = event.target as HTMLFormElement
    const formData = new FormData(form)
  },

  // Using currentTarget (often more reliable)
  onButtonClick(event: MouseEvent) {
    // currentTarget is the element the handler is attached to
    const button = event.currentTarget as HTMLButtonElement
    console.log(button.dataset.id)
  }
}

Template Usage

<template>
  <div>
    <!-- Mouse events -->
    <button @click="handleClick">Click me</button>

    <!-- Input events -->
    <input @input="handleInput" @keydown="handleKeydown" />

    <!-- Form events -->
    <form @submit.prevent="handleSubmit">
      <button type="submit">Submit</button>
    </form>
  </div>
</template>

With Custom Component Events

For custom component events, type based on what the component emits:

methods: {
  // Child emits: emit('update', { id: number, value: string })
  handleChildUpdate(payload: { id: number; value: string }) {
    console.log(payload.id, payload.value)
  },

  // Child emits primitive: emit('change', newValue)
  handleValueChange(newValue: number) {
    this.count = newValue
  }
}

Generic Event Handler Pattern

For reusable handlers:

methods: {
  // Generic handler that works with any input
  updateField<T extends HTMLInputElement | HTMLTextAreaElement>(
    field: keyof typeof this.$data,
    event: Event
  ) {
    const target = event.target as T
    ;(this as any)[field] = target.value
  }
}

Why currentTarget vs target?

  • target: The element that triggered the event (could be a child)
  • currentTarget: The element the event listener is attached to
methods: {
  // If button contains <span>Click</span>, clicking the span:
  // - event.target = span
  // - event.currentTarget = button
  handleClick(event: MouseEvent) {
    // Use currentTarget when you want the handler's element
    const button = event.currentTarget as HTMLButtonElement
  }
}

Reference

Source: SKILL.md on GitHub

No alerts17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    The skill provides comprehensive best practices and TypeScript integration guidelines for the Vue.js Options API. It contains educational content and code examples that are safe and consistent with official Vue.js documentation. No security issues were detected.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer7mo

    11 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at bc922e4. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 8 months ago
version
2.0.0
author
github.com/vuejs-ai
  • Vue
  • TypeScript
  • options-api
  • best-practices
  • lifecycle-hooks
  • prop-types
  • type-safety

README badge

README badge for hyf0/vue-skills/vue-options-api-best-practices

Teaches Vue 3 Options API patterns, TypeScript integration, and common mistakes like arrow functions in methods and lifecycle hooks. Covers prop typing, event handler safety, provide/inject limitations, and computed property type inference specific to the Options API style.

Generated from the current SKILL.md.

Does this skill cover Composition API?
No. This skill focuses exclusively on Options API patterns and does not include Composition API examples or guidance.
What TypeScript support does this provide?
The skill includes references for enabling type inference with defineComponent, typing event handlers, complex prop types, provide/inject limitations, and computed property return types in the Options API context.
Does this address method binding issues?
Yes. The skill covers arrow function pitfalls in methods and lifecycle hooks, which commonly break this context binding in the Options API.

Generated from the current SKILL.md. These answers refresh after source changes.