new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Vue · API reference · all subjects

composition-api/setup

55 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

expose() function limits properties exposed to parent component

expose() is a function that can be used to explicitly limit the properties exposed when the component instance is accessed by a parent component via template refs. Calling expose() with no arguments makes the instance closed and does not expose anything to the parent. Calling expose() with an object selectively exposes specified properties.

setup() hook entry point for Composition API

The setup() hook serves as the entry point for Composition API usage in components in two cases: when using Composition API without a build step, or when integrating with Composition-API-based code in an Options API component. For Single-File Components using Composition API, <script setup> is strongly recommended for more succinct and ergonomic syntax.

setup() return object exposes reactive state to template and component instance

Properties returned from setup() are made available both to the template and to the component instance via other Options API hooks. Refs returned from setup() are automatically shallow unwrapped when accessed in the template and on this, so you do not need to use .value when accessing them.

setup() this context and async restrictions

setup() does not have access to the component instance; this will have a value of undefined inside setup(). You can access Composition-API-exposed values from Options API, but not the other way around. setup() should return an object synchronously. The only case when async setup() can be used is when the component is a descendant of a Suspense component.

setup() props argument is reactive

The first argument in the setup function is the props argument. Props inside setup() are reactive and will be updated when new props are passed in.

Destructuring props loses reactivity

If you destructure the props object, the destructured variables will lose reactivity. It is therefore recommended to always access props in the form of props.xxx. To destructure props while retaining reactivity, use toRefs() to turn props into an object of refs before destructuring, or use toRef() to turn a single property into a ref.

setup() context object - second argument

The second argument passed to setup() is a Setup Context object. The context object exposes: attrs (non-reactive object, equivalent to $attrs), slots (non-reactive object, equivalent to $slots), emit (function, equivalent to $emit), and expose (function). The context object is not reactive and can be safely destructured.

attrs and slots are stateful but not reactive

attrs and slots are stateful objects that are always updated when the component itself is updated. This means you should avoid destructuring them and always reference properties as attrs.x or slots.x. Unlike props, the properties of attrs and slots are not reactive. If you intend to apply side effects based on changes to attrs or slots, you should do so inside an onBeforeUpdate lifecycle hook.

setup() can return a render function

setup() can return a render function which can directly make use of the reactive state declared in the same scope. Returning a render function prevents returning anything else. If you need to expose methods via template refs while returning a render function, you must call expose() to expose those methods.

setup() basic usage example

Example showing setup() with reactive state returned to template and accessed in Options API hooks: ```vue <script> import { ref } from 'vue' export default { setup() { const count = ref(0) // expose to template and other options API hooks return { count } }, mounted() { console.log(this.count) // 0 } } </script> <template> <button @click="count++">{{ count }}</button> </template> ``` This example demonstrates accessing reactive state in the template without .value and accessing it in Options API hooks via this.

Accessing props in setup() with toRefs example

Example showing how to destructure props while retaining reactivity using toRefs() and toRef(): ```js import { toRefs, toRef } from 'vue' export default { setup(props) { // turn `props` into an object of refs, then destructure const { title } = toRefs(props) // `title` is a ref that tracks `props.title` console.log(title.value) // OR, turn a single property on `props` into a ref const title = toRef(props, 'title') } } ``` This shows two approaches to destructuring props while maintaining reactivity.

setup() context object destructuring example

Example showing how to destructure the context object: ```js export default { setup(props, { attrs, slots, emit, expose }) { ... } } ``` The context object can be safely destructured since it is not reactive.

expose() in setup example

Example showing expose() usage to selectively expose properties: ```js export default { setup(props, { expose }) { // make the instance "closed" - // i.e. do not expose anything to the parent expose() const publicCount = ref(0) const privateCount = ref(0) // selectively expose local state expose({ count: publicCount }) } } ``` This demonstrates calling expose() with no arguments to close the instance, then later calling it with an object to selectively expose specific properties.

setup() with render function example

Example showing setup() returning a render function: ```js import { h, ref } from 'vue' export default { setup() { const count = ref(0) return () => h('div', count.value) } } ``` This demonstrates a render function directly using reactive state from setup().

setup() with render function and expose() example

Example showing how to expose methods when returning a render function from setup(): ```js import { h, ref } from 'vue' export default { setup(props, { expose }) { const count = ref(0) const increment = () => ++count.value expose({ increment }) return () => h('div', count.value) } } ``` The increment method becomes available in the parent component via a template ref.

Script setup basic syntax and behavior

To use script setup, add the setup attribute to the <script> block. Code inside <script setup> is compiled as the content of the component's setup() function. Unlike normal <script> which executes once when the component is first imported, code inside <script setup> executes every time an instance of the component is created.

Script setup top-level bindings exposed to template

Any top-level bindings declared inside <script setup>, including variables, function declarations, and imports, are directly usable in the template without needing to expose them via a methods option.

Refs automatically unwrapped in script setup templates

In <script setup>, reactive state needs to be explicitly created using Reactivity APIs. Refs are automatically unwrapped when referenced in templates, just like values returned from a setup() function.

Script setup component references as variables

In <script setup>, imported components are referenced as variables and can be used directly as custom component tag names in templates. PascalCase component tags are strongly recommended for consistency and to help differentiate from native custom elements.

Dynamic components in script setup

Since components in <script setup> are referenced as variables instead of registered under string keys, use dynamic :is binding when using dynamic components: <component :is="someCondition ? Foo : Bar" />. Components can be used as variables in ternary expressions.

Recursive components in script setup

An SFC can implicitly refer to itself via its filename. A file named FooBar.vue can refer to itself as <FooBar/> in its template. This has lower priority than imported components. If a named import conflicts with the component's inferred name, alias the import.

Namespaced components in script setup

Component tags with dots like <Foo.Bar> can be used to refer to components nested under object properties. This is useful when importing multiple components from a single file using import * as Form from './form-components'.

Custom directives in script setup naming convention

Local custom directives in <script setup> do not need to be explicitly registered, but must follow the naming scheme vNameOfDirective. Globally registered custom directives work normally. Imported directives can be renamed to fit the required naming scheme.

defineProps compiler macro

defineProps is a compiler macro automatically available inside <script setup> used to declare props with full type inference support. It does not need to be imported and is compiled away when <script setup> is processed. It accepts the same value as the props option. The options passed to defineProps will be hoisted out of setup into module scope, so they cannot reference local variables declared in setup scope but can reference imported bindings.

defineEmits compiler macro

defineEmits is a compiler macro automatically available inside <script setup> used to declare emitted events with full type inference support. It does not need to be imported and is compiled away when <script setup> is processed. It accepts the same value as the emits option. The options passed to defineEmits will be hoisted out of setup into module scope, so they cannot reference local variables declared in setup scope but can reference imported bindings.

Type-only props declaration syntax

Props can be declared using pure-type syntax by passing a literal type argument to defineProps: const props = defineProps<{ foo: string; bar?: number }>(). When using type declaration, the equivalent runtime declaration is automatically generated from static analysis. In dev mode, the compiler infers corresponding runtime validation from types. In prod mode, the compiler generates array format declaration to reduce bundle size.

Type-only emits declaration syntax

Emits can be declared using pure-type syntax by passing a literal type argument to defineEmits: const emit = defineEmits<{ (e: 'change', id: number): void; (e: 'update', value: string): void }>() or using the alternative syntax: const emit = defineEmits<{ change: [id: number]; update: [value: string] }>(). When using type declaration, the equivalent runtime declaration is automatically generated from static analysis.

Runtime and type declaration mutual exclusion

defineProps or defineEmits can only use either runtime declaration OR type declaration. Using both at the same time will result in a compile error.

Reactive props destructure in Vue 3.5+

In Vue 3.5 and above, variables destructured from the return value of defineProps are reactive. Vue's compiler automatically prepends props. when code in the same <script setup> block accesses variables destructured from defineProps. Default values can be declared using JavaScript's native default value syntax: const { msg = 'hello', labels = ['one', 'two'] } = defineProps<Props>()

withDefaults compiler macro for type-based props

In Vue 3.4 and below, when using type-based props declaration without Reactive Props Destructure, the withDefaults compiler macro is needed to declare default values: const props = withDefaults(defineProps<Props>(), { msg: 'hello', labels: () => ['one', 'two'] }). Default values for mutable reference types should be wrapped in functions to avoid accidental modification and external side effects. In 3.5+, default values can be declared directly with destructure syntax.

defineModel compiler macro

defineModel is a compiler macro available in 3.4+ used to declare a two-way binding prop that can be consumed via v-model from the parent component. If the first argument is a literal string, it will be used as the prop name; otherwise the prop name defaults to 'modelValue'. An additional object can include the prop's options and the model ref's value transform options. The macro emits an 'update:' event when the model is mutated.

defineModel examples

const model = defineModel() declares 'modelValue' prop, emits 'update:modelValue' when mutated. const model = defineModel({ type: String }) declares 'modelValue' prop with options. const count = defineModel('count') declares 'count' prop, emits 'update:count' when mutated. const count = defineModel('count', { type: Number, default: 0 }) declares 'count' prop with options.

defineModel de-synchronization pitfall

If defineModel has a default value and the parent does not provide a value for the prop, it can cause de-synchronization between parent and child components. For example, if a child has const model = defineModel({ default: 1 }) and the parent passes <Child v-model="myRef"></Child> where myRef is undefined, the parent's myRef is undefined but the child's model is 1.

defineModel modifiers destructuring

To access modifiers used with the v-model directive, destructure the return value of defineModel(): const [modelValue, modelModifiers] = defineModel(). This corresponds to v-model with modifiers like v-model.trim.

defineModel get and set transformers

Transform values when reading or syncing them back to parent using get and set transformer options in defineModel: const [modelValue, modelModifiers] = defineModel({ set(value) { if (modelModifiers.trim) { return value.trim() } return value } })

defineModel TypeScript usage

defineModel can receive type arguments: const modelValue = defineModel<string>() returns Ref<string | undefined>. const modelValue = defineModel<string>({ required: true }) returns Ref<string>. const [modelValue, modifiers] = defineModel<string, 'trim' | 'uppercase'>() receives Record<'trim' | 'uppercase', true | undefined>.

defineExpose compiler macro

Components using <script setup> are closed by default - the public instance retrieved via template refs or $parent chains will not expose any bindings declared inside <script setup>. Use the defineExpose compiler macro to explicitly expose properties: defineExpose({ a, b }). When a parent gets an instance via template refs, refs are automatically unwrapped just like on normal instances.

defineOptions compiler macro

defineOptions is a compiler macro available in 3.3+ used to declare component options directly inside <script setup> without a separate <script> block: defineOptions({ inheritAttrs: false, customOptions: { /* ... */ } }). The options will be hoisted to module scope and cannot access local variables in <script setup> that are not literal constants.

defineSlots TypeScript macro

defineSlots is a compiler macro available in 3.3+ used to provide type hints to IDEs for slot name and props type checking. It only accepts a type parameter and no runtime arguments. The type parameter should be a type literal where the property key is the slot name, and the value type is the slot function: defineSlots<{ default(props: { msg: string }): any }>(). It returns the slots object, equivalent to setupContext.slots or useSlots().

useSlots and useAttrs in script setup

useSlots and useAttrs helpers can be used inside <script setup> to access slots and attrs. They are actual runtime functions that return the equivalent of setupContext.slots and setupContext.attrs. They are imported from 'vue' and can be used in normal composition API functions as well. Access them directly as $slots and $attrs in templates instead.

Script setup with normal script block

script setup can be used alongside normal <script>. A normal <script> may be needed to declare options that cannot be expressed in <script setup>, declare named exports, or run side effects or create objects that should only execute once. Normal <script> is executed in module scope only once, while <script setup> is executed in setup() scope for each instance.

Script setup and normal script restrictions

Do NOT use a separate <script> section for options that can already be defined using <script setup>, such as props and emits. Variables created inside <script setup> are not added as properties to the component instance, making them inaccessible from the Options API. Mixing APIs in this way is strongly discouraged. If in an unsupported scenario, consider switching to an explicit setup() function instead.

Top-level await in script setup

Top-level await can be used inside <script setup>. The resulting code will be compiled as async setup(). The awaited expression will be automatically compiled in a format that preserves the current component instance context after the await. async setup() must be used in combination with Suspense, which is currently an experimental feature.

Generic type parameters in script setup

Generic type parameters can be declared using the generic attribute on the <script> tag: <script setup lang="ts" generic="T">. The value of generic works exactly the same as the parameter list between <...> in TypeScript. Multiple parameters, extends constraints, default types, and imported types can be used: generic="T extends string | number, U extends Item".

@vue-generic directive for explicit types

@vue-generic directive can be used to pass in explicit types when the type cannot be inferred: <!-- @vue-generic {import('@/api').Actor} --> <ApiSelect v-model="peopleIds" endpoint="/api/actors" id-prop="actorId" />

Generic component refs with vue-component-type-helpers

To use a reference to a generic component in a ref, use the vue-component-type-helpers library as InstanceType won't work. Import ComponentExposed from 'vue-component-type-helpers' and use: ref<ComponentExposed<typeof genericComponent>>() for generic components.

Script setup restrictions with src attribute

Due to the difference in module execution semantics, code inside <script setup> relies on the context of an SFC. When moved into external .js or .ts files, it may lead to confusion for both developers and tools. Therefore, <script setup> cannot be used with the src attribute.

Script setup does not support In-DOM Root Component Template

<script setup> does not support In-DOM Root Component Template.

Compiler macro limitations in script setup

defineProps and defineEmits are compiler macros only usable inside <script setup>. They do not need to be imported and are compiled away when <script setup> is processed. They cannot be conditionally used, moved to separate functions, or used with runtime values. The options passed cannot reference local variables in setup scope, only imported bindings.

Type declaration limitations for generic components in 3.2

In Vue 3.2 and below, the generic type parameter for defineProps() was limited to a type literal or a reference to a local interface. This limitation was resolved in 3.3. The latest version of Vue supports referencing imported and a limited set of complex types in the type parameter position. Complex types that require actual type analysis, like conditional types, are not supported for the entire props object but can be used for the type of a single prop.

Script setup is recommended syntax

<script setup> is the recommended syntax when using both SFCs and Composition API. It provides more succinct code with less boilerplate, ability to declare props and emitted events using pure TypeScript, better runtime performance (template is compiled into a render function in the same scope without an intermediate proxy), and better IDE type-inference performance.

script setup syntax automatic template access

Top-level imports, variables and functions declared in <script setup> are automatically usable in the template of the same component. The template behaves as a JavaScript function declared in the same scope and naturally has access to everything declared alongside it.

Reactive props destructuring with defineProps

When defineProps is used with destructuring in <script setup>, a compile-time transform applies automatically. This allows destructuring props while retaining reactivity and supporting default values and local aliasing directly in the destructuring pattern.

$$() on destructured props converts to toRef

When using $$() on destructured props, the compiler converts it with toRef for efficiency. The macro works on destructured props since they are reactive variables.

defineProps destructuring with defaults example

Example showing reactive props destructuring with defineProps: ```html <script setup lang="ts"> interface Props { msg: string count?: number foo?: string } const { msg, count = 1, foo: bar } = defineProps<Props>() watchEffect(() => { console.log(msg, count, bar) }) </script> ``` Default values and aliasing work directly in the destructuring pattern.

Give your agent this brain