or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

component-system.mdcustom-elements.mddevelopment-tools.mdindex.mdjsx-support.mdreactivity.mdrendering.mdsfc-compilation.mdssr.mdutilities.md
tile.json

component-system.mddocs/

Component System

Vue's component system provides a complete solution for building modular, reusable UI components with lifecycle management, composition API, dependency injection, and watchers.

Capabilities

Component Definition

Define Component

Creates Vue components with full TypeScript support and flexibility for both Options API and Composition API patterns.

/**
 * Define a component with full type inference
 * @param setup - Setup function for Composition API
 * @returns Component constructor
 */
function defineComponent<Props, RawBindings = object>(
  setup: (props: Props, ctx: SetupContext) => RawBindings | RenderFunction
): ComponentConstructor;

/**
 * Define a component with options object
 * @param options - Component options (Options API)
 * @returns Component constructor
 */
function defineComponent(options: ComponentOptions): ComponentConstructor;

interface SetupContext {
  attrs: Data;
  slots: Slots;
  emit: EmitFunction;
  expose: (exposed?: Record<string, any>) => void;
}

Usage Examples:

import { defineComponent, ref, computed } from "vue";

// Composition API
const Counter = defineComponent({
  props: {
    initialCount: {
      type: Number,
      default: 0
    }
  },
  emits: ['update'],
  setup(props, { emit }) {
    const count = ref(props.initialCount);
    
    const increment = () => {
      count.value++;
      emit('update', count.value);
    };
    
    return {
      count,
      increment
    };
  }
});

// Options API
const Button = defineComponent({
  props: ['label', 'disabled'],
  emits: ['click'],
  data() {
    return {
      pressed: false
    };
  },
  methods: {
    handleClick() {
      if (!this.disabled) {
        this.$emit('click');
      }
    }
  }
});

Async Components

Define components that load asynchronously with loading states and error handling.

/**
 * Define an async component that loads on demand
 * @param loader - Function that returns a Promise resolving to component
 * @returns Async component constructor
 */
function defineAsyncComponent<T extends Component = Component>(
  loader: AsyncComponentLoader<T>
): T;

/**
 * Define async component with advanced options
 * @param options - Async component options
 * @returns Async component constructor
 */
function defineAsyncComponent<T extends Component = Component>(
  options: AsyncComponentOptions<T>
): T;

type AsyncComponentLoader<T = Component> = () => Promise<T>;

interface AsyncComponentOptions<T = Component> {
  loader: AsyncComponentLoader<T>;
  loadingComponent?: Component;
  errorComponent?: Component;
  delay?: number;
  timeout?: number;
  suspensible?: boolean;
  onError?: (error: Error, retry: () => void, fail: () => void, attempts: number) => any;
}

Usage Example:

import { defineAsyncComponent } from "vue";

// Simple async component
const AsyncModal = defineAsyncComponent(() => import('./Modal.vue'));

// With loading and error states
const AsyncChart = defineAsyncComponent({
  loader: () => import('./Chart.vue'),
  loadingComponent: LoadingSpinner,
  errorComponent: ErrorMessage,
  delay: 200,
  timeout: 3000
});

Lifecycle Hooks

Vue provides lifecycle hooks for both Options API and Composition API patterns.

/**
 * Called before component is mounted
 * @param callback - Hook callback function
 */
function onBeforeMount(callback: () => void): void;

/**
 * Called after component is mounted
 * @param callback - Hook callback function
 */
function onMounted(callback: () => void): void;

/**
 * Called before component updates
 * @param callback - Hook callback function
 */
function onBeforeUpdate(callback: () => void): void;

/**
 * Called after component updates
 * @param callback - Hook callback function
 */
function onUpdated(callback: () => void): void;

/**
 * Called before component is unmounted
 * @param callback - Hook callback function
 */
function onBeforeUnmount(callback: () => void): void;

/**
 * Called after component is unmounted
 * @param callback - Hook callback function
 */
function onUnmounted(callback: () => void): void;

/**
 * Called when component is activated (KeepAlive)
 * @param callback - Hook callback function
 */
function onActivated(callback: () => void): void;

/**
 * Called when component is deactivated (KeepAlive)
 * @param callback - Hook callback function
 */
function onDeactivated(callback: () => void): void;

/**
 * Called when render is tracked (dev only)
 * @param callback - Hook callback function
 */
function onRenderTracked(callback: (event: DebuggerEvent) => void): void;

/**
 * Called when render is triggered (dev only)
 * @param callback - Hook callback function
 */
function onRenderTriggered(callback: (event: DebuggerEvent) => void): void;

/**
 * Called when error is captured
 * @param callback - Error handling callback
 */
function onErrorCaptured(
  callback: (error: Error, instance: ComponentPublicInstance | null, info: string) => boolean | void
): void;

/**
 * Called during SSR prefetch phase
 * @param callback - Prefetch callback function
 */
function onServerPrefetch(callback: () => Promise<any>): void;

Usage Example:

import { defineComponent, onMounted, onUnmounted, ref } from "vue";

export default defineComponent({
  setup() {
    const timer = ref(null);
    
    onMounted(() => {
      console.log('Component mounted');
      timer.value = setInterval(() => {
        console.log('Timer tick');
      }, 1000);
    });
    
    onUnmounted(() => {
      console.log('Component unmounted');
      if (timer.value) {
        clearInterval(timer.value);
      }
    });
    
    return {};
  }
});

Watch API

Reactive watchers for observing data changes with immediate execution, deep watching, and cleanup.

/**
 * Watch a reactive source and execute callback on changes
 * @param source - Reactive source to watch
 * @param callback - Callback function
 * @param options - Watch options
 * @returns Stop function
 */
function watch<T>(
  source: WatchSource<T>,
  callback: WatchCallback<T>,
  options?: WatchOptions
): WatchStopHandle;

/**
 * Watch multiple sources
 * @param sources - Array of sources to watch
 * @param callback - Callback function
 * @param options - Watch options
 * @returns Stop function
 */
function watch<T extends readonly unknown[]>(
  sources: [...T],
  callback: WatchCallback<T>,
  options?: WatchOptions
): WatchStopHandle;

/**
 * Watch effect that automatically tracks dependencies
 * @param effect - Effect function
 * @param options - Watch options
 * @returns Stop function
 */
function watchEffect(
  effect: WatchEffectCallback,
  options?: WatchEffectOptions
): WatchStopHandle;

/**
 * Watch effect that runs after component updates
 * @param effect - Effect function
 * @param options - Watch options
 * @returns Stop function
 */
function watchPostEffect(
  effect: WatchEffectCallback,
  options?: WatchEffectOptions
): WatchStopHandle;

/**
 * Watch effect that runs synchronously
 * @param effect - Effect function
 * @param options - Watch options
 * @returns Stop function
 */
function watchSyncEffect(
  effect: WatchEffectCallback,
  options?: WatchEffectOptions
): WatchStopHandle;

interface WatchOptions {
  immediate?: boolean;
  deep?: boolean;
  flush?: 'pre' | 'post' | 'sync';
  onTrack?: (event: DebuggerEvent) => void;
  onTrigger?: (event: DebuggerEvent) => void;
}

type WatchCallback<T> = (
  value: T,
  oldValue: T,
  onCleanup: (cleanupFn: () => void) => void
) => void;

type WatchEffectCallback = (onCleanup: (cleanupFn: () => void) => void) => void;

type WatchStopHandle = () => void;

/**
 * Traverse and track all reactive properties in an object
 * @param source - Object to traverse
 * @param seen - Set to track circular references  
 */
function traverse(source: any, seen?: Set<any>): void;

Usage Examples:

import { ref, watch, watchEffect } from "vue";

const count = ref(0);
const user = ref({ name: 'John', age: 30 });

// Watch single source
const stopWatcher = watch(count, (newVal, oldVal) => {
  console.log(`Count changed from ${oldVal} to ${newVal}`);
});

// Watch multiple sources
watch([count, user], ([newCount, newUser], [oldCount, oldUser]) => {
  console.log('Count or user changed');
});

// Deep watch
watch(user, (newUser, oldUser) => {
  console.log('User object changed deeply');
}, { deep: true });

// Watch effect (auto-tracks dependencies)
watchEffect(() => {
  console.log(`Current count: ${count.value}`);
});

// Cleanup
stopWatcher(); // Stop watching

Dependency Injection

Provide/inject pattern for passing data through component hierarchy without props drilling.

/**
 * Provide a value to descendant components
 * @param key - Injection key
 * @param value - Value to provide
 */
function provide<T>(key: InjectionKey<T> | string, value: T): void;

/**
 * Inject a provided value
 * @param key - Injection key
 * @param defaultValue - Default value if not provided
 * @returns Injected value
 */
function inject<T>(key: InjectionKey<T> | string): T | undefined;
function inject<T>(key: InjectionKey<T> | string, defaultValue: T): T;
function inject<T>(
  key: InjectionKey<T> | string,
  defaultValue: T,
  treatDefaultAsFactory: false
): T;
function inject<T>(
  key: InjectionKey<T> | string,
  defaultValue: () => T,
  treatDefaultAsFactory: true
): T;

/**
 * Check if injection context is available
 * @returns True if injection context exists
 */
function hasInjectionContext(): boolean;

interface InjectionKey<T> extends Symbol {}

Usage Example:

import { provide, inject, defineComponent } from "vue";

// Create injection key with type safety
const ThemeKey = Symbol('theme') as InjectionKey<{ color: string; mode: string }>;

// Parent component
const App = defineComponent({
  setup() {
    provide(ThemeKey, {
      color: 'blue',
      mode: 'dark'
    });
    
    return {};
  }
});

// Child component
const Button = defineComponent({
  setup() {
    const theme = inject(ThemeKey, { color: 'gray', mode: 'light' });
    
    return {
      theme
    };
  }
});

Setup Helpers

Utilities for accessing component context and creating reactive bindings in Composition API.

/**
 * Access component attrs in setup
 * @returns Component attrs object
 */
function useAttrs(): SetupContext['attrs'];

/**
 * Access component slots in setup
 * @returns Component slots object
 */
function useSlots(): SetupContext['slots'];

/**
 * Create two-way binding helper for v-model
 * @param props - Component props
 * @param name - Prop name
 * @param options - Model options
 * @returns Writable computed ref
 */
function useModel<T>(
  props: Record<string, any>,
  name: string,
  options?: UseModelOptions
): WritableComputedRef<T>;

/**
 * Get template reference
 * @param key - Template ref key
 * @returns Ref that will be populated with element/component
 */
function useTemplateRef<T>(key: string): Ref<T | null>;

/**
 * Generate unique ID for component instance
 * @returns Unique ID string
 */
function useId(): string;

interface UseModelOptions {
  passive?: boolean;
  defaultValue?: any;
  deep?: boolean;
}

Usage Example:

import { defineComponent, useAttrs, useSlots, useModel, useTemplateRef } from "vue";

const CustomInput = defineComponent({
  props: {
    modelValue: String,
    disabled: Boolean
  },
  emits: ['update:modelValue'],
  setup(props, { emit }) {
    const attrs = useAttrs();
    const slots = useSlots();
    
    // Two-way binding
    const model = useModel(props, 'modelValue');
    
    // Template ref
    const inputRef = useTemplateRef<HTMLInputElement>('input');
    
    return {
      attrs,
      slots,
      model,
      inputRef
    };
  }
});

Script Setup API

Compile-time macros for <script setup> that provide ergonomic APIs for common patterns.

/**
 * Define component props (compile-time)
 * @param propsOptions - Props definition
 * @returns Props object
 */
function defineProps<T = {}>(): T;
function defineProps<T>(propsOptions: T): T;

/**
 * Define component emits (compile-time)
 * @param emitOptions - Emits definition
 * @returns Emit function
 */
function defineEmits<T = {}>(): T;
function defineEmits<T>(emitOptions: T): T;

/**
 * Define exposed properties (compile-time)
 * @param exposed - Object with exposed properties
 */
function defineExpose<T = {}>(exposed?: T): void;

/**
 * Define component options (compile-time)
 * @param options - Component options
 */
function defineOptions(options: ComponentOptions): void;

/**
 * Define component slots (compile-time)
 * @param slots - Slots definition
 * @returns Slots object
 */
function defineSlots<T = {}>(): T;

/**
 * Define v-model binding (compile-time)
 * @param options - Model options
 * @returns Writable computed ref
 */
function defineModel<T = any>(options?: DefineModelOptions): WritableComputedRef<T>;
function defineModel<T = any>(name: string, options?: DefineModelOptions): WritableComputedRef<T>;

/**
 * Set default values for props (compile-time)
 * @param defaults - Default values object
 * @returns Props with defaults
 */
function withDefaults<T, D>(props: T, defaults: D): T & D;

interface DefineModelOptions {
  default?: any;
  local?: boolean;
}

Usage Example (in <script setup>):

// Component with script setup
const props = defineProps<{
  title: string;
  count?: number;
}>();

const emit = defineEmits<{
  update: [value: number];
  close: [];
}>();

// Model binding
const modelValue = defineModel<string>();

// Expose methods/properties
defineExpose({
  focus() {
    // Focus logic
  }
});

// Set defaults
const propsWithDefaults = withDefaults(defineProps<{
  count?: number;
  disabled?: boolean;
}>(), {
  count: 0,
  disabled: false
});

Current Instance

Access the current component instance and context.

/**
 * Get current component instance (only in setup or lifecycle hooks)
 * @returns Component instance or null
 */
function getCurrentInstance(): ComponentInternalInstance | null;

interface ComponentInternalInstance {
  uid: number;
  type: Component;
  parent: ComponentInternalInstance | null;
  appContext: AppContext;
  props: Data;
  attrs: Data;
  slots: InternalSlots;
  emit: EmitFn;
  exposed: Record<string, any> | null;
  setupState: Data;
  ctx: ComponentPublicInstance;
}

Type Definitions

interface Component {
  __vccOpts?: ComponentOptions;
  displayName?: string;
}

interface ComponentOptions {
  name?: string;
  props?: ComponentPropsOptions;
  emits?: ComponentEmitsOptions;
  setup?: ComponentSetupFunction;
  data?: ComponentDataFunction;
  computed?: ComponentComputedOptions;
  methods?: ComponentMethodsOptions;
  watch?: ComponentWatchOptions;
  components?: Record<string, Component>;
  directives?: Record<string, Directive>;
  // lifecycle hooks
  beforeCreate?: ComponentHook;
  created?: ComponentHook;
  beforeMount?: ComponentHook;
  mounted?: ComponentHook;
  beforeUpdate?: ComponentHook;
  updated?: ComponentHook;
  beforeUnmount?: ComponentHook;
  unmounted?: ComponentHook;
  activated?: ComponentHook;
  deactivated?: ComponentHook;
  errorCaptured?: ComponentErrorCapturedHook;
  serverPrefetch?: ComponentHook;
}

type ComponentSetupFunction = (
  props: Record<string, any>,
  ctx: SetupContext
) => RenderFunction | Record<string, any> | void;

interface SetupContext {
  attrs: Record<string, any>;
  slots: Slots;
  emit: EmitFunction;
  expose: (exposed?: Record<string, any>) => void;
}