CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vue--composition-api

Provides Vue 3 Composition API compatibility for Vue 2 applications with reactive state management and lifecycle hooks.

Pending
Overview
Eval results
Files

computed.mddocs/

Computed Properties

Derived reactive state that automatically updates when dependencies change. Computed properties provide cached, derived values that recalculate only when their reactive dependencies change.

Capabilities

Read-only Computed

Creates a computed property with a getter function that automatically tracks dependencies and caches results.

/**
 * Creates a read-only computed property
 * @param getter - Function that computes the value
 * @returns Read-only computed reference
 */
function computed<T>(getter: ComputedGetter<T>): ComputedRef<T>;

type ComputedGetter<T> = () => T;

interface ComputedRef<T = any> extends WritableComputedRef<T> {
  readonly value: T;
}

Usage Examples:

import { ref, computed } from "@vue/composition-api";

const count = ref(0);
const doubleCount = computed(() => count.value * 2);

console.log(doubleCount.value); // 0
count.value = 5;
console.log(doubleCount.value); // 10

// Complex computed with multiple dependencies
const firstName = ref("John");
const lastName = ref("Doe");
const fullName = computed(() => `${firstName.value} ${lastName.value}`);

console.log(fullName.value); // "John Doe"

Writable Computed

Creates a computed property with both getter and setter functions, allowing two-way binding and derived state manipulation.

/**
 * Creates a writable computed property
 * @param options - Object with get and set functions
 * @returns Writable computed reference
 */
function computed<T>(options: WritableComputedOptions<T>): WritableComputedRef<T>;

interface WritableComputedOptions<T> {
  get: ComputedGetter<T>;
  set: ComputedSetter<T>;
}

type ComputedSetter<T> = (value: T) => void;

interface WritableComputedRef<T> extends Ref<T> {
  readonly effect: ReactiveEffect<T>;
}

Usage Examples:

import { ref, computed } from "@vue/composition-api";

const firstName = ref("John");
const lastName = ref("Doe");

const fullName = computed({
  get: () => `${firstName.value} ${lastName.value}`,
  set: (value: string) => {
    const parts = value.split(" ");
    firstName.value = parts[0] || "";
    lastName.value = parts[1] || "";
  },
});

console.log(fullName.value); // "John Doe"

// Setting the computed value updates the underlying refs
fullName.value = "Jane Smith";
console.log(firstName.value); // "Jane"
console.log(lastName.value); // "Smith"

Advanced Computed Patterns

Advanced usage patterns for computed properties including conditional logic, async operations, and error handling.

Conditional Computed:

import { ref, computed } from "@vue/composition-api";

const user = ref<{ name: string; email?: string } | null>(null);
const displayName = computed(() => {
  if (!user.value) return "Guest";
  return user.value.email ? `${user.value.name} (${user.value.email})` : user.value.name;
});

// Computed with fallback values
const safeValue = computed(() => user.value?.name ?? "Unknown");

Computed with Complex Logic:

import { ref, reactive, computed } from "@vue/composition-api";

const items = ref([
  { id: 1, name: "Apple", category: "fruit", price: 1.2 },
  { id: 2, name: "Banana", category: "fruit", price: 0.8 },
  { id: 3, name: "Carrot", category: "vegetable", price: 0.6 },
]);

const filters = reactive({
  category: "",
  maxPrice: null as number | null,
  searchTerm: "",
});

const filteredItems = computed(() => {
  return items.value.filter((item) => {
    const matchesCategory = !filters.category || item.category === filters.category;
    const matchesPrice = !filters.maxPrice || item.price <= filters.maxPrice;
    const matchesSearch = !filters.searchTerm || 
      item.name.toLowerCase().includes(filters.searchTerm.toLowerCase());
    
    return matchesCategory && matchesPrice && matchesSearch;
  });
});

const itemStats = computed(() => ({
  total: filteredItems.value.length,
  avgPrice: filteredItems.value.reduce((sum, item) => sum + item.price, 0) / filteredItems.value.length || 0,
  categories: [...new Set(filteredItems.value.map(item => item.category))],
}));

Computed with Side Effects (Anti-pattern Warning):

import { ref, computed, watch } from "@vue/composition-api";

// ❌ Don't do this - computed should be pure
const badComputed = computed(() => {
  console.log("This runs on every access!"); // Side effect
  return someValue.value * 2;
});

// ✅ Use watchers for side effects instead
const someValue = ref(0);
const doubledValue = computed(() => someValue.value * 2);

watch(doubledValue, (newValue) => {
  console.log("Doubled value changed:", newValue);
});

Performance Considerations

Computed properties are cached and only recalculate when dependencies change, making them efficient for expensive operations.

import { ref, computed } from "@vue/composition-api";

const expensiveData = ref([/* large array */]);

// This computation only runs when expensiveData changes
const processedData = computed(() => {
  console.log("Processing data..."); // Only logs when dependencies change
  return expensiveData.value
    .filter(item => item.active)
    .map(item => ({ ...item, processed: true }))
    .sort((a, b) => a.priority - b.priority);
});

// Multiple accesses use the cached result
console.log(processedData.value); // Processes data
console.log(processedData.value); // Uses cache
console.log(processedData.value); // Uses cache

Computed in Component Setup

Typical usage patterns within Vue component setup functions.

import { defineComponent, ref, computed } from "@vue/composition-api";

export default defineComponent({
  props: {
    multiplier: {
      type: Number,
      default: 1,
    },
  },
  setup(props) {
    const baseValue = ref(10);
    
    // Computed property using props and reactive state
    const computedValue = computed(() => baseValue.value * props.multiplier);
    
    // Computed property for template usage
    const isEven = computed(() => computedValue.value % 2 === 0);
    
    // Writable computed for v-model compatibility
    const doubledBase = computed({
      get: () => baseValue.value * 2,
      set: (value) => {
        baseValue.value = value / 2;
      },
    });
    
    return {
      baseValue,
      computedValue,
      isEven,
      doubledBase,
    };
  },
});

Types

interface ComputedRef<T = any> extends WritableComputedRef<T> {
  readonly value: T;
}

interface WritableComputedRef<T> extends Ref<T> {
  readonly effect: ReactiveEffect<T>;
}

interface WritableComputedOptions<T> {
  get: ComputedGetter<T>;
  set: ComputedSetter<T>;
}

type ComputedGetter<T> = () => T;
type ComputedSetter<T> = (value: T) => void;

interface ReactiveEffect<T = any> {
  (): T;
  _isEffect: true;
  id: number;
  active: boolean;
  raw: () => T;
  deps: Array<Dep>;
  options: ReactiveEffectOptions;
}

interface ReactiveEffectOptions {
  lazy?: boolean;
  scheduler?: (job: ReactiveEffect) => void;
  onTrack?: (event: DebuggerEvent) => void;
  onTrigger?: (event: DebuggerEvent) => void;
  onStop?: () => void;
}

Install with Tessl CLI

npx tessl i tessl/npm-vue--composition-api

docs

advanced-features.md

component-utilities.md

computed.md

dependency-injection.md

index.md

lifecycle.md

reactive-state.md

types.md

watchers.md

tile.json