### Install vue-property-decorator Source: https://github.com/kaorun343/vue-property-decorator/blob/master/README.md Install the library using npm. ```bash npm i -S vue-property-decorator ``` -------------------------------- ### Basic @Provide Example Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Demonstrates how to provide a message from a parent component to its descendants. ```typescript import { Vue, Component, Provide, Inject } from 'vue-property-decorator' @Component export class ParentComponent extends Vue { @Provide() message = 'Hello from parent!' } ``` -------------------------------- ### Install vue-property-decorator Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/INDEX.md Install the necessary packages for vue-property-decorator, including Vue, vue-class-component, TypeScript, and reflect-metadata. ```bash npm install vue-property-decorator vue vue-class-component npm install -D typescript reflect-metadata ``` -------------------------------- ### Example Usage of InjectOptions Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/types.md Demonstrates injecting dependencies with custom keys and default values using @Inject. ```typescript @Component export class MyComponent extends Vue { // Inject with custom key and default @Inject({ from: 'userService', default: null }) userService!: any // Inject with symbol key and default @Inject({ from: serviceSymbol, default: {} }) service!: any } ``` -------------------------------- ### Basic PropSync Usage Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/PropSync.md Demonstrates the basic setup for @PropSync in a child component and its usage with the .sync modifier in a parent component. ```typescript import { Vue, Component, PropSync } from 'vue-property-decorator' @Component export default class ChildComponent extends Vue { @PropSync('name', { type: String }) syncedName!: string } ``` ```html // ParentComponent.vue ``` -------------------------------- ### Theme Provider Example Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Demonstrates how to provide a theme object to child components using the @Provide decorator and inject it using the @Inject decorator. ```typescript @Component class ThemeProvider extends Vue { @Provide('theme') theme = { primary: '#007bff', secondary: '#6c757d' } } @Component class StyledComponent extends Vue { @Inject('theme') theme!: any } ``` -------------------------------- ### Install vue-property-decorator Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/configuration.md Install vue-property-decorator as a peer dependency alongside vue-class-component. Also install vue-class-component and reflect-metadata as dev dependencies. ```bash npm install --save vue-property-decorator npm install --save-dev vue-class-component reflect-metadata ``` -------------------------------- ### Basic VModel with String Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/VModel.md Demonstrates a basic VModel setup for a string property. Use this for simple text inputs. ```typescript import { Vue, Component, VModel } from 'vue-property-decorator' @Component export default class TextInputComponent extends Vue { @VModel() value!: string updateValue(newValue: string) { this.value = newValue } } ``` ```vue ``` -------------------------------- ### Runtime Setup with Reflect Metadata Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/INDEX.md Import 'reflect-metadata' once at your application's entry point. This is required for decorators to function correctly at runtime. ```typescript import 'reflect-metadata' // Import once at app entry import Vue from 'vue' import App from './App.vue' new Vue({ render: h => h(App) }).$mount('#app') ``` -------------------------------- ### Vue Provide with String Key Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Example of using a string as a key for the @Provide decorator. ```typescript import { Provide } from 'vue-property-decorator'; class MyComponent { @Provide('myKey') value = 'test' } ``` -------------------------------- ### package.json Scripts for Build and Development Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/configuration.md Defines common npm scripts for building the project, running tests, starting the development server, and linting code. ```json { "scripts": { "build": "tsc -p ./src/tsconfig.json && rollup -c", "test": "jest", "dev": "vue-cli-service serve", "lint": "eslint --ext .ts,.tsx,.vue src" } } ``` -------------------------------- ### Service Injection Example Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Illustrates providing multiple services like a logger and an API client using @Provide and injecting them into a data component with @Inject. ```typescript @Component class ServiceProvider extends Vue { @Provide('logger') logger = console @Provide('api') api = new APIClient() } @Component class DataComponent extends Vue { @Inject('logger') logger!: Console @Inject('api') api!: APIClient } ``` -------------------------------- ### Basic @Inject Example Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Shows how a child component can inject and use a message provided by an ancestor. ```typescript @Component export class ChildComponent extends Vue { @Inject() message!: string // Receives 'Hello from parent!' } ``` -------------------------------- ### Basic Vue Component Class Setup Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/configuration.md Defines a Vue component using class syntax and decorators. Includes properties, props, lifecycle hooks, and methods. ```typescript import { Vue, Component, Prop } from 'vue-property-decorator' @Component export default class MyComponent extends Vue { // Properties message = 'Hello' // Prop @Prop(String) title!: string // Lifecycle mounted() { console.log('Component mounted') } // Methods greet() { return `${this.message}, ${this.title}` } } ``` -------------------------------- ### Setup Reflect-Metadata in Entry Point Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/configuration.md Import 'reflect-metadata' once at the top of your main entry point file (e.g., main.ts) before any Vue components are defined to enable automatic type inference from decorators. ```typescript import 'reflect-metadata' import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false new Vue({ render: h => h(App) }).$mount('#app') ``` -------------------------------- ### Prop Decorator Usage Examples Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Prop.md Illustrates various ways to use the @Prop decorator, including simple type declarations, default values, multiple types, validation, and inference with reflect-metadata. ```APIDOC ## Usage Examples ### Simple type prop with constructor ```typescript import { Vue, Component, Prop } from 'vue-property-decorator' @Component export default class MyComponent extends Vue { @Prop(String) readonly name!: string @Prop(Number) readonly age!: number } ``` ### Prop with default value ```typescript @Component export default class MyComponent extends Vue { @Prop({ default: 'Guest' }) readonly name!: string @Prop({ type: Number, default: 0 }) readonly count!: number } ``` ### Prop with multiple accepted types ```typescript @Component export default class MyComponent extends Vue { @Prop([String, Number]) readonly value!: string | number } ``` ### Prop with validation ```typescript @Component export default class MyComponent extends Vue { @Prop({ type: Number, required: true, validator: (value: number) => value > 0 }) readonly quantity!: number } ``` ### Using with reflect-metadata ```typescript import 'reflect-metadata' import { Vue, Component, Prop } from 'vue-property-decorator' @Component export default class MyComponent extends Vue { @Prop() readonly age!: number // Type automatically inferred as Number } ``` ### Parent component passing props ```typescript ``` -------------------------------- ### Single Model Example Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Model.md Illustrates a component with a single string v-model. Vue 2.x supports only one v-model per component directly. ```typescript @Component export default class SingleModelComponent extends Vue { @Model('change', { type: String }) readonly value!: string } ``` -------------------------------- ### Complex Example: Form Field Component Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/VModel.md A comprehensive example of a form field component with VModel, including input handling, blur events, and validation. This pattern is reusable for various form inputs. ```typescript @Component export default class FormField extends Vue { @VModel({ type: String }) value!: string errorMessage = '' isTouched = false onInput(event: Event) { const target = event.target as HTMLInputElement this.value = target.value this.validate() } onBlur() { this.isTouched = true this.validate() } validate() { if (this.value.length === 0) { this.errorMessage = 'This field is required' } else if (this.value.length < 3) { this.errorMessage = 'Minimum 3 characters' } else { this.errorMessage = '' } } get hasError() { return this.isTouched && this.errorMessage.length > 0 } } ``` ```vue ``` ```vue ``` -------------------------------- ### PropSync with Reflect Metadata Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/PropSync.md Example of using @PropSync when 'reflect-metadata' is enabled, allowing type inference from the TypeScript annotation. ```typescript import 'reflect-metadata' import { Vue, Component, PropSync } from 'vue-property-decorator' @Component export default class ChildComponent extends Vue { @PropSync('count') currentCount!: number // Type inferred from annotation } ``` -------------------------------- ### Webpack ts-loader Configuration Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/configuration.md Example ts-loader configuration for Webpack, specifying the tsconfig.json file. This is relevant for projects not using Vue CLI. ```javascript { test: /\.tsx?$/, use: [ { loader: 'ts-loader', options: { configFile: 'tsconfig.json' } } ] } ``` -------------------------------- ### Complex Scenario with Multiple Synced Props Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/PropSync.md An example showcasing the use of multiple @PropSync decorators within a single component to manage several two-way bound props. ```APIDOC ## Complex scenario with multiple synced props ### Description This example illustrates how to use multiple `@PropSync` decorators within a single component to manage several two-way bound props simultaneously. Changes to `syncedEmail` or `syncedAge` will emit corresponding update events. ### Child Component Usage ```typescript @Component export default class FormComponent extends Vue { @PropSync('email', { type: String, required: true }) syncedEmail!: string @PropSync('age', { type: Number }) syncedAge!: number onSubmit() { // Changes to syncedEmail or syncedAge emit update events this.syncedEmail = this.syncedEmail.toLowerCase() this.syncedAge += 1 } } ``` ``` -------------------------------- ### Complex Async Workflow with @Emit and Error Handling Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Emit.md This example demonstrates a complex asynchronous operation where the @Emit decorator is used for success events, and manual $emit is used for error events. It also shows how to manage component state during async operations. ```typescript @Component export default class APIComponent extends Vue { isLoading = false @Emit('fetch-complete') async fetchUserData(userId: number) { this.isLoading = true try { const response = await fetch(`/api/users/${userId}`) const user = await response.json() this.isLoading = false return user } catch (error) { this.isLoading = false this.$emit('fetch-error', error) throw error } } } ``` ```html // Parent usage ``` -------------------------------- ### Basic Reactive Provide Example Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/ProvideReactive-InjectReactive.md Use @ProvideReactive to make a property reactive and automatically update child components. The child component uses @InjectReactive to access this reactive property. ```typescript import { Vue, Component, ProvideReactive, InjectReactive } from 'vue-property-decorator' @Component export class ParentComponent extends Vue { @ProvideReactive() count = 0 increment() { this.count++ // Child components automatically see this change } } ``` ```typescript @Component export class ChildComponent extends Vue { @InjectReactive() count!: number created() { // Will always have the latest value from parent console.log(this.count) } } ``` -------------------------------- ### Form Field Refs with Validation Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Ref.md Access form input elements via refs to get their values and apply validation logic or styling. This example shows email and password validation. ```typescript @Component export default class FormValidation extends Vue { @Ref('emailInput') readonly email!: HTMLInputElement @Ref('passwordInput') readonly password!: HTMLInputElement validateForm() { const isEmailValid = this.validateEmail() const isPasswordValid = this.validatePassword() return isEmailValid && isPasswordValid } validateEmail() { const value = this.email?.value || '' const isValid = /^[^- -Ÿ   -    ]+@[^- -Ÿ   -    ]+.[^- -Ÿ   -    ]+$/.test(value) this.email?.classList.toggle('error', !isValid) return isValid } validatePassword() { const value = this.password?.value || '' const isValid = value.length >= 8 this.password?.classList.toggle('error', !isValid) return isValid } submitForm() { if (this.validateForm()) { console.log('Form is valid, submitting...') } } } ``` ```vue ``` -------------------------------- ### Provide Application Configuration Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Demonstrates providing a complex configuration object for application-wide use. ```typescript interface AppConfig { apiUrl: string maxRetries: number timeout: number } @Component export class AppComponent extends Vue { @Provide('appConfig') config: AppConfig = { apiUrl: 'https://api.example.com', maxRetries: 3, timeout: 5000 } } ``` -------------------------------- ### Watch Nested Path Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Watch.md Watch a specific nested property within an array or object. This example watches the 'items' array itself. ```typescript @Component export default class ListComponent extends Vue { items = [ { id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' } ] @Watch('items') onItemsChanged() { console.log('Items array changed') } } ``` -------------------------------- ### With default values and reactivity Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/ProvideReactive-InjectReactive.md Explains how to provide default values for injected reactive properties and how to update them reactively. ```APIDOC ## With default values and reactivity ### Settings Provider ```typescript import { Vue, Component, ProvideReactive } from 'vue-property-decorator' const settingsKey = Symbol('AppSettings') @Component export class SettingsProvider extends Vue { @ProvideReactive(settingsKey) settings = { fontSize: 14, darkMode: false, notifications: true } updateSetting(key: string, value: any) { this.settings[key] = value } } ``` ### Settings Consumer ```typescript import { Vue, Component, InjectReactive } from 'vue-property-decorator' @Component export class SettingsConsumer extends Vue { @InjectReactive({ from: settingsKey, default: { fontSize: 14, darkMode: false, notifications: true } }) settings!: any toggleDarkMode() { this.settings.darkMode = !this.settings.darkMode } changeFontSize(size: number) { this.settings.fontSize = size } } ``` ``` -------------------------------- ### Reactive state management Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/ProvideReactive-InjectReactive.md Illustrates how to manage complex reactive state, such as theme, language, and user information, using a Symbol as a key for providing and injecting. ```APIDOC ## Reactive state management ### State Provider ```typescript import { Vue, Component, ProvideReactive } from 'vue-property-decorator' const stateKey = Symbol('appState') @Component export class StateProvider extends Vue { @ProvideReactive(stateKey) state = { theme: 'light', language: 'en', user: null } setTheme(theme: string) { this.state.theme = theme // Reactive update } setLanguage(language: string) { this.state.language = language // Reactive update } } ``` ### State Consumer ```typescript import { Vue, Component, InjectReactive } from 'vue-property-decorator' @Component export class StateConsumer extends Vue { @InjectReactive(stateKey) state!: any toggleTheme() { const newTheme = this.state.theme === 'light' ? 'dark' : 'light' // Parent's setTheme will be called } get currentLanguage() { return this.state.language // Reactive } } ``` ``` -------------------------------- ### Vue Equivalent Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Prop.md Demonstrates how the @Prop decorator usage translates to the standard Vue 'props' option in JavaScript. ```APIDOC ## Vue Equivalent The following decorator usage: ```typescript @Component class MyComponent extends Vue { @Prop(String) name!: string @Prop({ default: 5 }) count!: number } ``` Is equivalent to: ```javascript export default { props: { name: { type: String }, count: { default: 5 } } } ``` ``` -------------------------------- ### Provide with Custom Keys Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Illustrates providing values using both Symbol keys and string keys for custom injection. ```typescript const symbolKey = Symbol('customKey') @Component export class ParentComponent extends Vue { @Provide(symbolKey) secret = 'This is a secret' @Provide('apiUrl') apiUrl = 'https://api.example.com' } ``` -------------------------------- ### Vue @Model Decorator Example Source: https://github.com/kaorun343/vue-property-decorator/blob/master/README.md Defines a model property for v-model binding. The first argument is the event name, and the second is the prop options. ```typescript import { Vue, Component, Model } from 'vue-property-decorator' @Component export default class YourComponent extends Vue { @Model('change', { type: Boolean }) readonly checked!: boolean } ``` ```javascript export default { model: { prop: 'checked', event: 'change', }, props: { checked: { type: Boolean, }, }, } ``` -------------------------------- ### Vue @PropSync Decorator Example Source: https://github.com/kaorun343/vue-property-decorator/blob/master/README.md Synchronizes a prop with a computed property, allowing two-way binding. The first argument to @PropSync is the prop name. ```typescript import { Vue, Component, PropSync } from 'vue-property-decorator' @Component export default class YourComponent extends Vue { @PropSync('name', { type: String }) syncedName!: string } ``` ```javascript export default { props: { name: { type: String, }, }, computed: { syncedName: { get() { return this.name }, set(value) { this.$emit('update:name', value) }, }, }, } ``` -------------------------------- ### Refs in Lifecycle Hooks Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Ref.md Refs are guaranteed to be available in lifecycle hooks like `mounted`. Use them for DOM manipulation or setup after the component has been rendered. ```typescript @Component export default class LifecycleRefComponent extends Vue { @Ref() readonly container!: HTMLDivElement mounted() { // Ref is available after component is mounted console.log('Container:', this.container) this.setupContainer() } setupContainer() { this.container?.classList.add('initialized') } beforeDestroy() { // Cleanup if needed this.container?.classList.remove('initialized') } } ``` -------------------------------- ### Vue Provide/Inject JavaScript Equivalent Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Shows the equivalent JavaScript implementation for the @Provide and @Inject decorator usage in Vue components. ```javascript // ParentComponent export default { data() { return { msg: 'Hello' } }, provide() { return { message: this.msg } } } // ChildComponent export default { inject: { message: 'message' } } ``` -------------------------------- ### Accessing DOM Elements with Ref Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/INDEX.md Use the Ref decorator to get a reference to a DOM element within a Vue component for direct manipulation. ```typescript @Component export class Form extends Vue { @Ref() readonly input!: HTMLInputElement submit() { const value = this.input?.value } } ``` -------------------------------- ### Vue Component with @Watch Decorator Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Watch.md Example of using the @Watch decorator to observe changes in a component property. It demonstrates immediate and deep watching options. ```typescript import Vue from 'vue' import Component from 'vue-class-component' @Component class UserComponent extends Vue { userName = '' @Watch('userName', { immediate: true, deep: true }) onUserNameChanged(newValue: string, oldValue: string) { console.log(newValue) } } ``` -------------------------------- ### ThemeProvider Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/ProvideReactive-InjectReactive.md Provides a reactive theme configuration using @ProvideReactive. Includes a method to update the theme. ```APIDOC ## ThemeProvider ### Description Provides a reactive theme configuration using the @ProvideReactive decorator. Child components can inject this theme to style their elements accordingly. ### Methods #### setTheme(newTheme: ThemeConfig) Updates the current theme configuration with new values. The changes are reactive across all injected instances. ### Provided Properties - **theme** (ThemeConfig): A reactive object containing theme properties like `primary`, `secondary`, and `background` colors. ``` -------------------------------- ### Reactive service injection Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/ProvideReactive-InjectReactive.md Shows how to inject reactive services, like a notification service, allowing components to interact with and receive updates from the service instance. ```APIDOC ## Reactive service injection ### Service Definition ```typescript class NotificationService { messages: string[] = [] addMessage(msg: string) { this.messages.push(msg) } removeMessage(index: number) { this.messages.splice(index, 1) } } ``` ### Service Provider ```typescript import { Vue, Component, ProvideReactive } from 'vue-property-decorator' const serviceKey = Symbol('NotificationService') @Component export class AppComponent extends Vue { @ProvideReactive(serviceKey) service = new NotificationService() notify(message: string) { this.service.addMessage(message) } } ``` ### Service Consumer ```typescript import { Vue, Component, InjectReactive } from 'vue-property-decorator' @Component export class NotificationCenter extends Vue { @InjectReactive(serviceKey) service!: NotificationService get messages() { return this.service.messages // Reactive, updates when service changes } clearMessage(index: number) { this.service.removeMessage(index) } } ``` ``` -------------------------------- ### Vue Provide/Inject Decorator Usage Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Demonstrates the usage of @Provide and @Inject decorators for dependency injection between parent and child Vue components. ```typescript import { Component, Provide, Inject } from 'vue-property-decorator'; import Vue from 'vue'; @Component class ParentComponent extends Vue { @Provide('message') msg = 'Hello' } @Component class ChildComponent extends Vue { @Inject('message') message!: string } ``` -------------------------------- ### Vue Equivalent of @Prop Decorator Usage Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Prop.md Shows the equivalent Vue JavaScript options object configuration for the provided @Prop decorator usage. ```javascript export default { props: { name: { type: String }, count: { default: 5 } } } ``` -------------------------------- ### Equivalent Vue Options API for ProvideReactive Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/ProvideReactive-InjectReactive.md Shows the equivalent Vue.js options API implementation for providing reactive state, corresponding to the @ProvideReactive decorator. ```javascript export default { data() { return { count: 0 } }, provide() { return { __reactiveInject__: this, count: this.count } } } ``` -------------------------------- ### Dynamic Template Rendering with @Ref Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Ref.md Use @Ref to get a typed reference to a DOM element for dynamic content manipulation. Ensure the element exists before accessing its properties. ```typescript @Component export default class DynamicRefComponent extends Vue { @Ref() readonly content!: HTMLDivElement updateContent(html: string) { if (this.content) { this.content.innerHTML = html } } getContentHeight() { return this.content?.offsetHeight || 0 } scrollToTop() { this.content?.scrollTo({ top: 0, behavior: 'smooth' }) } } ``` -------------------------------- ### Inject Application Configuration Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Shows how a component can inject and utilize the application configuration provided by an ancestor. ```typescript @Component export class APIClient extends Vue { @Inject('appConfig') config!: AppConfig async fetch(endpoint: string) { const url = `${this.config.apiUrl}${endpoint}` // Use config } } ``` -------------------------------- ### Vue Provide with Symbol Key Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Demonstrates using a Symbol as an injection key with the @Provide decorator, which is preferred for internal APIs to prevent naming conflicts. ```typescript import { Provide } from 'vue-property-decorator'; const internalKey = Symbol('internal'); class MyComponent { @Provide(internalKey) value = 'secret' } ``` -------------------------------- ### VModel Decorator Usage Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/VModel.md This example demonstrates how to use the @VModel decorator to create a typed property that supports two-way binding. The type of the 'value' property is inferred from the TypeScript annotation. ```APIDOC ## @VModel ### Description The `@VModel` decorator is used to declare a property that supports two-way data binding using Vue's `v-model` directive. It automatically configures the component to accept a `value` prop and emit an `input` event, which is the standard convention for `v-model`. ### Usage ```typescript import 'reflect-metadata' import { Vue, Component, VModel } from 'vue-property-decorator' @Component export default class TypedVModelComponent extends Vue { @VModel() // Type inferred from annotation value!: number } ``` ### Vue Equivalent The decorator usage is equivalent to the following Vue component options: ```javascript export default { model: { prop: 'value', event: 'input' }, props: { value: { type: String } // Type can be specified, e.g., { type: String } }, computed: { value: { get() { return this.value }, set(value) { this.$emit('input', value) } } } } ``` ### Parent Component Usage Parent components can bind to this component using the `v-model` directive: ```vue ``` ### Comparison with other decorators - **`@VModel`**: Fixed prop name ('value') and event name ('input'). Simplest for standard v-model usage. - **`@Model`**: Custom prop and event names. Offers most flexibility. - **`@ModelSync`**: Custom prop and event names, similar to `@Model` but with a computed property for direct modification. ``` -------------------------------- ### Emitting Without Explicit Event Name Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Emit.md Demonstrates emitting events using the default naming convention (kebab-case of method name) for methods that return values or have arguments. ```APIDOC ## Emitting without explicit event name ### Usage Example ```typescript import { Vue, Component, Emit } from 'vue-property-decorator' @Component export default class ActionComponent extends Vue { @Emit() onClicked() { // Method name converted: onClicked → on-clicked return { timestamp: Date.now() } } @Emit() userDataChanged() { // userDataChanged → user-data-changed return this.userData } } ``` ``` -------------------------------- ### Measure DOM Element with @Ref Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Ref.md Get the dimensions of a DOM element using @Ref. This pattern is helpful for layout calculations or animations. Ensure the ref is correctly typed as an element. ```typescript @Ref() readonly container!: HTMLDivElement getWidth() { return this.container?.clientWidth || 0 } getHeight() { return this.container?.clientHeight || 0 } ``` -------------------------------- ### Inject with Symbol Keys for Type Safety Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Shows how to inject services using Symbol keys, ensuring type safety and avoiding key collisions. ```typescript // ChildComponent @Component export class ChildComponent extends Vue { @Inject(userServiceKey) userService!: any @Inject(authServiceKey) authService!: any created() { const user = this.userService.getUser() const authenticated = this.authService.isAuthenticated } } ``` -------------------------------- ### Dropdown/Select Input Wrapper with @VModel Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/VModel.md Implement a custom select or dropdown component using @VModel for easy integration with v-model. This example shows how to bind the selected option to the `value` prop. ```typescript @Component export default class SelectInput extends Vue { @VModel({ type: String }) value!: string options = ['A', 'B', 'C'] } ``` -------------------------------- ### Emitting with Arguments and Return Value Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Emit.md When a method has both a return value and arguments, the return value is emitted as the first argument, followed by the original method arguments. ```APIDOC ## Emitting with Arguments and Return Value Original method arguments follow the return value ### Usage Example ```typescript import { Vue, Component, Emit } from 'vue-property-decorator' @Component export default class FormComponent extends Vue { @Emit() submitForm(data: any) { // Return value becomes first argument return { success: true, timestamp: Date.now() } } } ``` ```html // Parent receives return value as first arg, followed by original args ``` ``` -------------------------------- ### Configure TypeScript for Decorators Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/INDEX.md Enable experimental decorators and emit decorator metadata in your TypeScript configuration file. ```json { "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } } ``` -------------------------------- ### Reactive user context Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/ProvideReactive-InjectReactive.md Demonstrates providing and injecting a reactive user context, enabling components to access and react to changes in user authentication status and profile information. ```APIDOC ## Reactive user context ### User Context Provider ```typescript import { Vue, Component, ProvideReactive } from 'vue-property-decorator' interface User { id: number name: string role: string } const userContextKey = Symbol('UserContext') @Component export class AppComponent extends Vue { @ProvideReactive(userContextKey) userContext: User | null = null async login(credentials: any) { const user = await this.authenticateUser(credentials) this.userContext = user // Reactive update to all children } logout() { this.userContext = null // Reactive update } } ``` ### User Context Consumers ```typescript import { Vue, Component, InjectReactive } from 'vue-property-decorator' @Component export class AuthGuard extends Vue { @InjectReactive(userContextKey) userContext!: User | null get isAuthenticated() { return this.userContext !== null } get userName() { return this.userContext?.name || 'Guest' } } @Component export class UserProfile extends Vue { @InjectReactive(userContextKey) userContext!: User | null get role() { return this.userContext?.role || 'visitor' } } ``` ``` -------------------------------- ### Vue @Prop Decorator Example Source: https://github.com/kaorun343/vue-property-decorator/blob/master/README.md Defines component props using the @Prop decorator. Ensure default values are defined as shown; direct assignment like `@Prop() prop = 'default value'` is not supported. ```typescript import { Vue, Component, Prop } from 'vue-property-decorator' @Component export default class YourComponent extends Vue { @Prop(Number) readonly propA: number | undefined @Prop({ default: 'default value' }) readonly propB!: string @Prop([String, Boolean]) readonly propC: string | boolean | undefined } ``` ```javascript export default { props: { propA: { type: Number, }, propB: { default: 'default value', }, propC: { type: [String, Boolean], }, }, } ``` -------------------------------- ### Watch Different Paths with Different Handlers and Shared Handler Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Watch.md Demonstrates watching distinct properties with their own handlers, as well as a shared handler that triggers for changes in either property. ```typescript @Component export default class DebugComponent extends Vue { count = 0 message = '' @Watch('count') onCountChanged(newValue: number, oldValue: number) { console.log(`Count: ${oldValue} → ${newValue}`) } @Watch('message') onMessageChanged(newValue: string, oldValue: string) { console.log(`Message: ${oldValue} → ${newValue}`) } @Watch('count') @Watch('message') onAnyChanged() { console.log('Something changed!') } } ``` -------------------------------- ### Reactive State Management with Symbols Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/ProvideReactive-InjectReactive.md Demonstrates providing and injecting a complex reactive state object using a Symbol as a key. Changes to the state object are reactive. ```typescript const stateKey = Symbol('appState') @Component export class StateProvider extends Vue { @ProvideReactive(stateKey) state = { theme: 'light', language: 'en', user: null } setTheme(theme: string) { this.state.theme = theme // Reactive update } setLanguage(language: string) { this.state.language = language // Reactive update } } ``` ```typescript @Component export class StateConsumer extends Vue { @InjectReactive(stateKey) state!: any toggleTheme() { const newTheme = this.state.theme === 'light' ? 'dark' : 'light' // Parent's setTheme will be called } get currentLanguage() { return this.state.language // Reactive } } ``` -------------------------------- ### Equivalent Vue Options API for InjectReactive Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/ProvideReactive-InjectReactive.md Illustrates the equivalent Vue.js options API implementation for injecting reactive state, corresponding to the @InjectReactive decorator. ```javascript export default { inject: { __reactiveInject__: { from: '__reactiveInject__', default: {} } }, computed: { count() { const obj = this.__reactiveInject__ return obj ? obj.count : undefined } } } ``` -------------------------------- ### Provide Reactive Theme Configuration Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/ProvideReactive-InjectReactive.md Provides a reactive theme object using @ProvideReactive. This allows for dynamic theme changes that propagate to consuming components. ```typescript interface ThemeConfig { primary: string secondary: string background: string } const themeKey = Symbol('Theme') @Component export class ThemeProvider extends Vue { @ProvideReactive(themeKey) theme: ThemeConfig = { primary: '#007bff', secondary: '#6c757d', background: '#ffffff' } setTheme(newTheme: ThemeConfig) { Object.assign(this.theme, newTheme) } } ``` -------------------------------- ### Vue Property Decorator File Structure Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/INDEX.md Overview of the directory structure for the vue-property-decorator library, including source, compiled output, and test directories. ```tree vue-property-decorator/ ├── src/ │ ├── decorators/ │ │ ├── Prop.ts │ │ ├── PropSync.ts │ │ ├── Model.ts │ │ ├── ModelSync.ts │ │ ├── Watch.ts │ │ ├── Emit.ts │ │ ├── Provide.ts │ │ ├── Inject.ts │ │ ├── ProvideReactive.ts │ │ ├── InjectReactive.ts │ │ ├── Ref.ts │ │ └── VModel.ts │ ├── helpers/ │ │ ├── metadata.ts (reflect-metadata type inference) │ │ └── provideInject.ts (provide/inject implementation) │ └── index.ts (main entry point) ├── lib/ (compiled output) ├── tests/ ├── package.json └── README.md ``` -------------------------------- ### Global State Management with ProvideReactive and InjectReactive Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/INDEX.md Implement a simplified global state management pattern using ProvideReactive and InjectReactive decorators for dependency injection. ```typescript const stateKey = Symbol('state') @Component export class Provider extends Vue { @ProvideReactive(stateKey) state = { count: 0 } } @Component export class Consumer extends Vue { @InjectReactive(stateKey) state!: any } ``` -------------------------------- ### Watch with Immediate and Deep Options Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Watch.md Combine `immediate: true` and `deep: true` to trigger the watcher immediately upon component creation and to observe nested property changes. ```typescript @Component export default class ConfigComponent extends Vue { config = { theme: 'light', settings: { fontSize: 14 } } @Watch('config', { immediate: true, deep: true }) onConfigChanged(newValue: any) { console.log('Config updated:', newValue) this.applyConfig(newValue) } applyConfig(config: any) { // Apply configuration to the component } } ``` -------------------------------- ### TodoProvider Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/ProvideReactive-InjectReactive.md Provides a reactive list of todos using @ProvideReactive. Includes methods to add and toggle todos. ```APIDOC ## TodoProvider ### Description Provides a reactive list of todos using the @ProvideReactive decorator. This allows child components to inject and react to changes in the todo list. ### Methods #### addTodo(title: string) Adds a new todo item to the reactive list. #### toggleTodo(id: number) Finds a todo by its ID and toggles its `completed` status. This change is reactive across all injected instances. ### Provided Properties - **todos** (Todo[]): A reactive array of Todo objects. The `Todo` interface includes `id`, `title`, and `completed` properties. ``` -------------------------------- ### Equivalent Vue Component without Decorators Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Emit.md Shows the equivalent Vue component logic using direct $emit calls, illustrating the verbosity compared to the @Emit decorator. ```javascript export default { data() { return { count: 0 } }, methods: { increment() { this.count++; this.$emit('increment'); }, customMethod(value) { const result = value * 2; this.$emit('custom-event', result, value); return result; } } } ``` -------------------------------- ### Vue @Ref Decorator vs. Native $refs Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Ref.md Illustrates the equivalence between using the @Ref decorator and the native Vue $refs computed property. ```typescript @Component class FormComponent extends Vue { @Ref() readonly input!: HTMLInputElement @Ref('button') readonly submitBtn!: HTMLButtonElement } ``` ```javascript export default { computed: { input: { cache: false, get() { return this.$refs.input } }, submitBtn: { cache: false, get() { return this.$refs.button } } } } ``` -------------------------------- ### Inject and Use Provided Methods Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Demonstrates how a child component can inject and call methods provided by an ancestor. ```typescript @Component export class ConsumerComponent extends Vue { @Inject('store') store!: any useStore() { this.store.increment() console.log(this.store.value) } } ``` -------------------------------- ### Emitting with Multiple Arguments Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Emit.md All arguments passed to the decorated method are forwarded to the emitted event, after the return value (if any). ```APIDOC ## Emitting with Multiple Arguments Original arguments are forwarded ### Usage Example ```typescript import { Vue, Component, Emit } from 'vue-property-decorator' @Component export default class DataComponent extends Vue { @Emit() processData(id: number, name: string) { // Original arguments are forwarded return { processed: true } } } ``` ```html // Parent receives: processed result, id, and name ``` ``` -------------------------------- ### @Provide / @Inject Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/CONTENTS.txt Implements non-reactive dependency injection using Symbol or string keys, with support for default values and multi-level nesting. ```APIDOC ## @Provide / @Inject ### Description Implements non-reactive dependency injection using Symbol or string keys, with support for default values and multi-level nesting. ### Method Decorator ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example N/A ### Response #### Success Response (200) N/A #### Response Example N/A ### Notes - Non-reactive dependency injection - Symbol and string keys, default values - Multi-level nesting patterns - Source file location: API-REFERENCE/Provide-Inject.md (400 lines) ``` -------------------------------- ### Inject with Custom Keys Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Demonstrates injecting values that were provided using custom Symbol or string keys. ```typescript @Component export class ChildComponent extends Vue { @Inject(symbolKey) secret!: string @Inject('apiUrl') apiUrl!: string } ``` -------------------------------- ### Provide Methods for Injection Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Illustrates providing methods from a parent component to be used by child components. ```typescript @Component export class StoreComponent extends Vue { value = 0 increment() { this.value++ } @Provide('store') getStore() { return { value: this.value, increment: this.increment } } } ``` -------------------------------- ### Emitting Without Arguments Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Emit.md Demonstrates how to emit an event when a method has no return value and no arguments, simply to signal an action or state change. ```APIDOC ## Emitting without arguments ### Usage Example ```typescript import { Vue, Component, Emit } from 'vue-property-decorator' @Component export default class SimpleComponent extends Vue { @Emit() notifyReady() { // No return value, no arguments // Simply emits 'notify-ready' event } } ``` ```html // Parent ``` ``` -------------------------------- ### Provide with Default Values Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Shows how to provide a value that can be injected by child components. ```typescript @Component export class ParentComponent extends Vue { @Provide('theme') currentTheme = 'light' } ``` -------------------------------- ### Basic reactive provide and inject Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/ProvideReactive-InjectReactive.md Demonstrates the fundamental usage of @ProvideReactive in a parent component and @InjectReactive in a child component to share a reactive count property. ```APIDOC ## Basic reactive provide and inject ### Parent Component ```typescript import { Vue, Component, ProvideReactive } from 'vue-property-decorator' @Component export class ParentComponent extends Vue { @ProvideReactive() count = 0 increment() { this.count++ // Child components automatically see this change } } ``` ### Child Component ```typescript import { Vue, Component, InjectReactive } from 'vue-property-decorator' @Component export class ChildComponent extends Vue { @InjectReactive() count!: number created() { // Will always have the latest value from parent console.log(this.count) } } ``` ``` -------------------------------- ### @ProvideReactive / @InjectReactive Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/CONTENTS.txt Implements reactive dependency injection, supporting deep reactivity, theme systems, and state management with performance considerations. ```APIDOC ## @ProvideReactive / @InjectReactive ### Description Implements reactive dependency injection, supporting deep reactivity, theme systems, and state management with performance considerations. ### Method Decorator ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example N/A ### Response #### Success Response (200) N/A #### Response Example N/A ### Notes - Reactive dependency injection implementation - Deep reactivity, theme systems, state management - Performance and implementation details - Source file location: API-REFERENCE/ProvideReactive-InjectReactive.md (516 lines) ``` -------------------------------- ### Vue Provide with Class Key Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/Provide-Inject.md Illustrates using a class or constructor as the injection key for the @Provide decorator. ```typescript import { Provide } from 'vue-property-decorator'; class Service {} class MyComponent { @Provide(Service) service = new Service() } ``` -------------------------------- ### ProvideReactive with Default Values Source: https://github.com/kaorun343/vue-property-decorator/blob/master/_autodocs/api-reference/ProvideReactive-InjectReactive.md Shows how to provide reactive settings with default values. @InjectReactive can also specify default values if the provided value is not found. ```typescript const settingsKey = Symbol('AppSettings') @Component export class SettingsProvider extends Vue { @ProvideReactive(settingsKey) settings = { fontSize: 14, darkMode: false, notifications: true } updateSetting(key: string, value: any) { this.settings[key] = value } } ``` ```typescript @Component export class SettingsConsumer extends Vue { @InjectReactive({ from: settingsKey, default: { fontSize: 14, darkMode: false, notifications: true } }) settings!: any toggleDarkMode() { this.settings.darkMode = !this.settings.darkMode } changeFontSize(size: number) { this.settings.fontSize = size } } ```