CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vue-property-decorator

TypeScript decorators for Vue.js class-based components with property binding, state management, and lifecycle capabilities

Pending
Overview
Eval results
Files

base-components.mddocs/

Base Components

Re-exported components and utilities from vue-class-component and Vue core. These provide the foundational elements for class-based Vue component development and are essential for building components with decorators.

Capabilities

Component Decorator

The core class decorator that transforms TypeScript classes into Vue components, enabling the class-based component syntax.

/**
 * Class decorator that transforms TypeScript classes into Vue components
 * @param options - Vue component options object (optional)
 * @returns Decorated Vue component class
 */
const Component: ComponentDecorator;

interface ComponentDecorator {
  <V extends VueClass<Vue>>(target: V): V;
  <V extends VueClass<Vue>>(options: ComponentOptions<Vue>): (target: V) => V;
}

interface ComponentOptions<V extends Vue> {
  name?: string;
  components?: { [key: string]: Component | AsyncComponent };
  directives?: { [key: string]: DirectiveFunction | DirectiveOptions };
  filters?: { [key: string]: Function };
  mixins?: ComponentOptions<Vue>[];
  extends?: ComponentOptions<Vue>;
  template?: string;
  render?(createElement: CreateElement, hack: RenderContext<V>): VNode;
  renderError?(createElement: CreateElement, err: Error): VNode;
  staticRenderFns?: (() => VNode)[];
  beforeCreate?(this: V): void;
  created?(this: V): void;
  beforeMount?(this: V): void;
  mounted?(this: V): void;
  beforeUpdate?(this: V): void;
  updated?(this: V): void;
  activated?(this: V): void;
  deactivated?(this: V): void;
  beforeDestroy?(this: V): void;
  destroyed?(this: V): void;
  errorCaptured?(this: V, err: Error, instance: Vue, info: string): boolean | void;
}

Usage Examples:

import { Vue, Component } from "vue-property-decorator";

// Basic component
@Component
export default class BasicComponent extends Vue {
  message = "Hello World";
}

// Component with options
@Component({
  name: "MyCustomComponent",
  components: {
    ChildComponent: () => import("./ChildComponent.vue")
  },
  template: `
    <div>
      <h1>{{ title }}</h1>
      <child-component />
    </div>
  `
})
export default class CustomComponent extends Vue {
  title = "Custom Component";
}

// Component with lifecycle hooks
@Component
export default class LifecycleComponent extends Vue {
  data = [];

  created() {
    console.log("Component created");
    this.fetchData();
  }

  mounted() {
    console.log("Component mounted");
  }

  beforeDestroy() {
    console.log("Component will be destroyed");
    this.cleanup();
  }

  private async fetchData() {
    // Fetch data implementation
  }

  private cleanup() {
    // Cleanup implementation
  }
}

Vue Base Class

The core Vue constructor class that provides all Vue instance methods and properties for class-based components.

/**
 * Vue base class providing all Vue instance methods and properties
 */
const Vue: VueConstructor;

interface VueConstructor {
  new <Data = object, Methods = object, Computed = object, Props = object>(
    options?: ComponentOptions<Vue, Data, Methods, Computed, Props>
  ): CombinedVueInstance<Vue, Data, Methods, Computed, Props>;
  
  extend<Data, Methods, Computed, Props>(
    options?: ComponentOptions<Vue, Data, Methods, Computed, Props>
  ): ExtendedVue<Vue, Data, Methods, Computed, Props>;
  
  component(id: string): VueConstructor;
  component<Props>(id: string, definition: Component<any, any, any, Props>): ExtendedVue<Vue, {}, {}, {}, Props>;
  
  use<T>(plugin: PluginFunction<T>, options?: T): VueConstructor;
  use(plugin: PluginObject<any> | PluginFunction<any>, ...options: any[]): VueConstructor;
  
  mixin(mixin: VueConstructor | ComponentOptions<Vue>): VueConstructor;
  
  directive(id: string): DirectiveOptions;
  directive(id: string, definition: DirectiveOptions | DirectiveFunction): VueConstructor;
  
  filter(id: string): Function;
  filter(id: string, definition: Function): VueConstructor;
  
  compile(template: string): {
    render(this: Component): VNode;
    staticRenderFns: (() => VNode)[];
  };
  
  config: VueConfiguration;
  version: string;
}

Usage Examples:

import { Vue, Component } from "vue-property-decorator";

@Component
export default class MyComponent extends Vue {
  // Vue instance properties and methods are available
  message = "Hello";

  // Access Vue instance methods
  updateMessage() {
    this.$nextTick(() => {
      console.log("DOM updated");
    });
  }

  // Access reactive data methods
  setData() {
    this.$set(this.someObject, "newKey", "newValue");
  }

  // Emit events
  handleClick() {
    this.$emit("custom-event", { data: this.message });
  }

  // Access lifecycle
  mounted() {
    console.log("Component element:", this.$el);
    console.log("Parent component:", this.$parent);
    console.log("Root component:", this.$root);
  }
}

Mixins Function

Helper function for creating mixed component classes, enabling composition of multiple component behaviors.

/**
 * Helper function for creating mixed component classes
 * @param mixins - Array of Vue classes to mix
 * @returns Mixed Vue class constructor
 */
function Mixins(...mixins: VueClass<Vue>[]): VueClass<Vue>;

type VueClass<V> = {
  new(...args: any[]): V & Vue;
} & typeof Vue;

Usage Examples:

import { Vue, Component, Mixins } from "vue-property-decorator";

// Define mixin classes
@Component
class TimestampMixin extends Vue {
  created() {
    console.log(`Component created at: ${new Date().toISOString()}`);
  }
  
  getTimestamp() {
    return Date.now();
  }
}

@Component
class ValidationMixin extends Vue {
  errors: any = {};
  
  validate(data: any): boolean {
    // Validation logic
    return Object.keys(this.errors).length === 0;
  }
  
  clearErrors() {
    this.errors = {};
  }
}

// Use mixins in component
@Component
export default class MixedComponent extends Mixins(TimestampMixin, ValidationMixin) {
  formData = {};
  
  // Now has access to methods from both mixins
  handleSubmit() {
    if (this.validate(this.formData)) {
      console.log(`Form submitted at: ${this.getTimestamp()}`);
    }
  }
  
  resetForm() {
    this.formData = {};
    this.clearErrors(); // From ValidationMixin
  }
}

// Advanced mixin with generics
@Component
class DataMixin<T> extends Vue {
  data: T[] = [];
  loading = false;
  
  async fetchData(url: string): Promise<T[]> {
    this.loading = true;
    try {
      const response = await fetch(url);
      this.data = await response.json();
      return this.data;
    } finally {
      this.loading = false;
    }
  }
}

// Use generic mixin
interface User {
  id: number;
  name: string;
  email: string;
}

@Component
export default class UserList extends Mixins(DataMixin) {
  async mounted() {
    await this.fetchData("/api/users");
  }
  
  get users(): User[] {
    return this.data as User[];
  }
}

Advanced Usage Patterns

Component Factory Pattern

import { Vue, Component } from "vue-property-decorator";

// Base component with common functionality
@Component
class BaseFormComponent extends Vue {
  loading = false;
  errors: any = {};
  
  protected async submitForm(data: any): Promise<void> {
    this.loading = true;
    this.errors = {};
    
    try {
      await this.performSubmit(data);
      this.$emit("success", data);
    } catch (error) {
      this.errors = error.response?.data?.errors || { general: error.message };
      this.$emit("error", error);
    } finally {
      this.loading = false;
    }
  }
  
  protected async performSubmit(data: any): Promise<void> {
    // Override in subclasses
    throw new Error("performSubmit must be implemented");
  }
}

// Specific form implementation
@Component
export default class UserRegistrationForm extends BaseFormComponent {
  userData = {
    name: "",
    email: "",
    password: ""
  };
  
  protected async performSubmit(data: any): Promise<void> {
    const response = await fetch("/api/register", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data)
    });
    
    if (!response.ok) {
      throw new Error("Registration failed");
    }
  }
  
  handleSubmit() {
    this.submitForm(this.userData);
  }
}

Plugin Integration

import { Vue, Component } from "vue-property-decorator";

// Extend Vue with plugin types
declare module "vue/types/vue" {
  interface Vue {
    $http: {
      get(url: string): Promise<any>;
      post(url: string, data: any): Promise<any>;
    };
    $notify: {
      success(message: string): void;
      error(message: string): void;
    };
  }
}

@Component
export default class PluginAwareComponent extends Vue {
  async loadData() {
    try {
      const data = await this.$http.get("/api/data");
      this.$notify.success("Data loaded successfully");
      return data;
    } catch (error) {
      this.$notify.error("Failed to load data");
      throw error;
    }
  }
}

Types

interface ComponentOptions<V extends Vue, Data = DefaultData<V>, Methods = DefaultMethods<V>, Computed = DefaultComputed, Props = DefaultProps> {
  data?: Data;
  props?: Props;
  propsData?: object;
  computed?: Computed;
  methods?: Methods;
  watch?: Record<string, WatchOptionsWithHandler<any> | WatchHandler<any>>;
  el?: Element | string;
  template?: string;
  render?(createElement: CreateElement, hack: RenderContext<V>): VNode;
  renderError?(createElement: CreateElement, err: Error): VNode;
  staticRenderFns?: (() => VNode)[];
  beforeCreate?(this: V): void;
  created?(this: V): void;
  beforeMount?(this: V): void;
  mounted?(this: V): void;
  beforeUpdate?(this: V): void;
  updated?(this: V): void;
  activated?(this: V): void;
  deactivated?(this: V): void;
  beforeDestroy?(this: V): void;
  destroyed?(this: V): void;
  errorCaptured?(this: V, err: Error, instance: Vue, info: string): boolean | void;
  directives?: { [key: string]: DirectiveFunction | DirectiveOptions };
  components?: { [key: string]: Component | AsyncComponent };
  transitions?: { [key: string]: object };
  filters?: { [key: string]: Function };
  provide?: object | (() => object);
  inject?: InjectOptions;
  model?: { prop?: string; event?: string };
  parent?: Vue;
  mixins?: (VueConstructor | ComponentOptions<Vue>)[];
  name?: string;
  extends?: VueConstructor | ComponentOptions<Vue>;
  delimiters?: [string, string];
  comments?: boolean;
  inheritAttrs?: boolean;
}

type VueClass<V> = { new(...args: any[]): V & Vue } & typeof Vue;
type ComponentDecorator = <V extends VueClass<Vue>>(target: V) => V;

Install with Tessl CLI

npx tessl i tessl/npm-vue-property-decorator

docs

base-components.md

component-properties.md

dependency-injection.md

index.md

lifecycle-events.md

tile.json