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 · Guide · all subjects

components

198 notes in this subject, read out of this brain and free to use. This is page 3 of 4.

createApp function creates application instance

Every Vue application starts by creating a new application instance with the createApp function. The argument passed to createApp is a component object, which becomes the root component.

Root component structure

Every Vue app requires a root component that can contain other components as its children. In Single-File Components, the root component is typically imported from a .vue file and passed to createApp.

mount method renders app to DOM

An application instance will not render anything until its .mount() method is called. The mount method expects a container argument, which can be either an actual DOM element or a selector string. The root component's content is rendered inside the container element, which itself is not considered part of the app.

mount method must be called after all configurations

The .mount() method should always be called after all app configurations and asset registrations are done. The return value of mount is the root component instance, unlike asset registration methods which return the application instance.

In-DOM root component template

A template for the root component can be provided by writing it directly inside the mount container instead of in the component itself. Vue will automatically use the container's innerHTML as the template if the root component does not have a template option. In-DOM templates are useful in applications using Vue without a build step or in conjunction with server-side frameworks.

app.config object for app-level configuration

The application instance exposes a .config object that allows configuration of app-level options, such as defining an app-level error handler via app.config.errorHandler that captures errors from all descendant components.

app.component registers global components

The application instance provides the app.component() method to register app-scoped components. A registered component becomes available for use anywhere in the app. For example: app.component('TodoDeleteButton', TodoDeleteButton) makes the component available globally.

Multiple application instances on same page

Multiple Vue applications can co-exist on the same page using the createApp API. Each application has its own scope for configuration and global assets. Multiple small application instances should be created and mounted on specific elements rather than mounting a single instance on the entire page when enhancing server-rendered HTML.

Class binding on components with single root element

When using the class attribute or :class directive on a component with a single root element, those classes are added to the component's root element and merged with existing classes. Example: <MyComponent class="baz" /> where the child template is <p class="foo bar">Hi!</p> renders as <p class="foo bar baz">Hi!</p>.

Class binding on components with multiple root elements

When a component has multiple root elements, use the $attrs component property to define which element receives bound classes. Example: <p :class="$attrs.class">Hi!</p> in the child template allows classes passed to the component to be applied to the specific element.

Component definition with Single-File Component syntax

A Vue component in Single-File Component format (.vue) contains a <script> section with component options or <script setup> with Composition API, and a <template> section with markup. Example using Options API: <script> exports default object with data() method returning state, and template interpolates values with {{ }}. Example using Composition API: <script setup> imports ref from vue, creates reactive variables with ref(), and template automatically has access to them.

Component definition without build step

When not using a build step, a Vue component can be defined as a plain JavaScript object with Vue-specific options. The object contains a template property with a string template, or an 'is' attribute pointing to an element ID. Options API example uses data() method. Composition API example uses setup() function returning refs and reactive state.

Registering imported components in Options API

To use an imported child component in the parent's template, register it using the components option in the default export. Pass an object with the component as a value: components: { ButtonCounter }. The component will then be available as a tag using the registered key name.

Imported components are automatically available in Composition API with script setup

When using <script setup> in Composition API, imported components are automatically made available to the template without requiring explicit registration. Simply import the component and use it as a tag in the template.

Component instances are separate

Each time a component is used, a new instance of it is created. This means reused components maintain separate state; changes in one instance do not affect other instances of the same component.

PascalCase tag names for components in SFC

In Single-File Components, child components should use PascalCase tag names (e.g., ButtonCounter) to differentiate from native HTML elements. SFC is a compiled format supporting case-sensitive tag names and self-closing syntax (/>).

kebab-case component names in in-DOM templates

When templates are written directly in the DOM (as content of native <template> elements), components must use kebab-case names (e.g., button-counter) and explicit closing tags due to browser HTML parsing behavior making tag names case-insensitive.

Props declaration with Options API

Props are declared using the props option in a component's default export. Props can be declared as an array of strings, e.g., props: ['title']. Props become properties on the component instance and are accessible in the template and on this context.

Props declaration with defineProps macro

In <script setup>, use the defineProps macro to declare props: defineProps(['title']). defineProps is a compile-time macro available only in <script setup> and does not require explicit import. It returns an object containing all passed props, allowing JavaScript access: const props = defineProps(['title']); console.log(props.title).

Passing props to components

Props are passed to components as custom attributes with values. Static values: <BlogPost title="My journey with Vue" />. Dynamic values use v-bind syntax: <BlogPost :title="post.title" />. Multiple component instances can receive different prop values.

Dynamic component switching with component element

Use the <component> element with the special is attribute to dynamically switch between components: <component :is="currentTab"></component> or <component :is="tabs[currentTab]"></component>. The value passed to :is can be the name string of a registered component or the actual imported component object.

Using is attribute with regular HTML elements

The is attribute on the <component> element can also create regular HTML elements by passing the element name as a string.

KeepAlive component preserves component state

When switching between multiple components with <component :is="..">, a component is unmounted when switched away from. Use the built-in <KeepAlive> component to force inactive components to stay 'alive' and preserve their state.

Case insensitivity in in-DOM templates

HTML tags and attribute names are case-insensitive in browsers. When using in-DOM templates, PascalCase component names, camelCased prop names, and camelCased v-on event names must use kebab-cased equivalents. Example: JavaScript camelCase prop 'postTitle' becomes 'post-title' in HTML.

Self-closing tags in in-DOM templates

In in-DOM templates, components must always include explicit closing tags: <my-component></my-component>. Self-closing syntax <my-component /> is not valid in in-DOM HTML because the HTML spec only allows specific void elements like <input> and <img> to omit closing tags. Omitting closing tags causes the browser's HTML parser to misinterpret nesting.

Element placement restrictions workaround with is attribute

Some HTML elements like <ul>, <ol>, <table>, and <select> restrict what elements can appear inside them. Using a custom component inside these elements causes hoisting errors. Workaround: use the special is attribute on a native element: <table><tr is="vue:blog-post-row"></tr></table>. The value must be prefixed with 'vue:' when used on native HTML elements.

v-model with custom components

Vue components can be built with customized form input behavior and used with v-model. This allows creating reusable inputs with custom functionality that work with v-model syntax. Details on implementing v-model with components are available in the Components guide.

Template refs on child components

The ref attribute can be used on child components to get a reference to the component instance. When using Options API or components not using <script setup>, the referenced instance is identical to the child component's this, giving the parent full access to every property and method.

defineExpose macro for <script setup> components

Components using <script setup> are private by default. Use the defineExpose macro to explicitly expose a public interface that parent components can access via template refs. The macro must be called before any await operation, or properties and methods exposed after the await will not be accessible. Refs are automatically unwrapped in the exposed interface.

expose option for Options API components

In Options API, use the expose option to limit access to a child instance when referenced via template ref. Pass an array of property and method names that should be accessible: expose: ['publicData', 'publicMethod']. Only listed items will be accessible to parent components.

Component refs should be used sparingly

Component refs should only be used when absolutely necessary because they create tightly coupled implementations between parent and child. In most cases, use standard props and emit interfaces for parent-child interactions instead.

$$() on destructured props with toRef

When using $$() on destructured props, the compiler converts it to use toRef for efficiency. For example: const { count } = defineProps<{ count: number }>(); passAsRef($$(count)) compiles to: const __props_count = toRef(props, 'count'); passAsRef(__props_count).

Reactive props destructure with defineProps

When destructuring defineProps() in <script setup> with Reactivity Transform enabled, destructured variables remain reactive and update automatically. Default values work with simple assignment syntax (count = 1), and local aliasing is supported (foo: bar). The compiler converts this to runtime prop declarations with appropriate type and default configurations.

Functional component signature in Composition API

The signature of a functional component in Composition API is the same as the setup() hook: function MyComponent(props, { slots, emit, attrs }) { ... }.

Functional component signature in Options API

In Options API, functional components receive props as the first argument and context as the second. Context contains three properties: attrs (equivalent to $attrs), emit (equivalent to $emit), and slots (equivalent to $slots). No 'this' reference is available for functional components.

Functional components as plain functions

A component can be declared as a plain function without needing an options object. This is a valid Vue component if it returns a valid render output. For example, function Hello() { return 'hello world!' } is a valid component.

Defining props and emits for functional components

Props and emits can be defined for functional components as properties: MyComponent.props = ['value']; MyComponent.emits = ['click']. If the props option is not specified, the props object will contain all attributes (same as attrs), and prop names will not be normalized to camelCase.

Attribute fallthrough for functional components

For functional components with explicit props, attribute fallthrough works like normal components. For functional components without explicit props, only class, style, and onXxx event listeners inherit from attrs by default. Use inheritAttrs = false to disable attribute inheritance: MyComponent.inheritAttrs = false.

Functional components registration and consumption

Functional components can be registered and consumed just like normal components. If you pass a function as the first argument to h(), it will be treated as a functional component.

Named functional component TypeScript typing

A named functional component can be typed by defining prop and event types, then assigning props and emits properties. Example: type FComponentProps = { message: string }; type Events = { sendMessage(message: string): void }; function FComponent(props: FComponentProps, context: SetupContext<Events>) { return <button onClick={() => context.emit('sendMessage', props.message)}>{props.message}</button> }; FComponent.props = { message: { type: String, required: true } }; FComponent.emits = { sendMessage: (value: unknown) => typeof value === 'string' };

Anonymous functional component TypeScript typing

An anonymous functional component can be typed using the FunctionalComponent generic type: import type { FunctionalComponent } from 'vue'; type FComponentProps = { message: string }; type Events = { sendMessage(message: string): void }; const FComponent: FunctionalComponent<FComponentProps, Events> = (props, context) => { return <button onClick={() => context.emit('sendMessage', props.message)}>{props.message}</button> }; FComponent.props = { message: { type: String, required: true } }; FComponent.emits = { sendMessage: (value) => typeof value === 'string' };

resolveComponent() for dynamically registered components

If a component is registered by name and cannot be imported directly (for example, globally registered by a library), use the resolveComponent() helper to resolve it programmatically in render functions.

Components in render functions

To create a vnode for a component, pass the component definition as the first argument to h(). When using render functions, components do not need to be registered - imported components can be used directly: h(Foo) or h(Bar). Dynamic components are straightforward: ok.value ? h(Foo) : h(Bar). In JSX: <Foo /> or <Bar />.

Functional components definition

Functional components are stateless components that act like pure functions: props in, vnodes out. They are rendered without creating a component instance (no 'this') and without lifecycle hooks. Declare them as plain functions rather than options objects. The function is effectively the render function for the component.

Custom element lifecycle with Vue

A Vue custom element mounts an internal Vue component instance inside its shadow root when the element's connectedCallback is called for the first time. When disconnectedCallback is invoked, Vue checks if the element is detached from the document after a microtask tick. If still in the document, it's a move and the component instance is preserved. If detached, it's a removal and the component instance is unmounted.

Custom element props reflection behavior

All props declared using the props option are defined on the custom element as properties. Vue automatically handles reflection between attributes and properties: attributes are always reflected to corresponding properties, and properties with primitive values (string, boolean, number) are reflected as attributes. Vue automatically casts Boolean and Number type props to their desired types when set as attributes.

Custom element Boolean and Number type casting example

With props declaration: ```js props: { selected: Boolean, index: Number } ``` And usage: ```vue-html <my-element selected index="1"></my-element> ``` In the component, selected will be cast to true (boolean) and index will be cast to 1 (number).

Custom element slots use native syntax

Slots can be rendered using the <slot/> element inside the component as usual. However, when consuming the resulting element, it only accepts native slots syntax. Scoped slots are not supported. When passing named slots, use the slot attribute instead of the v-slot directive: ```vue-html <my-element> <div slot="named">hello</div> </my-element> ```

Provide/Inject with custom elements

The Provide/Inject API and its Composition API equivalent work between Vue-defined custom elements, but only between custom elements. A Vue-defined custom element cannot inject properties provided by a non-custom-element Vue component.

configureApp option for custom elements

Configure the app instance of a Vue custom element using the configureApp option passed to defineCustomElement: ```js defineCustomElement(MyComponent, { configureApp(app) { app.config.errorHandler = (err) => { /* ... */ } } }) ```

SFC custom element mode example

```js import { defineCustomElement } from 'vue' import Example from './Example.ce.vue' console.log(Example.styles) // ["/* inlined css */"] // convert into custom element constructor const ExampleElement = defineCustomElement(Example) // register customElements.define('my-example', ExampleElement) ```

Custom element library export pattern

It is recommended to export individual element constructors to give users flexibility to import them on-demand and register them with desired tag names. Also export a convenience function to automatically register all elements. Example entry point: ```js import { defineCustomElement } from 'vue' import Foo from './MyFoo.ce.vue' import Bar from './MyBar.ce.vue' const MyFoo = defineCustomElement(Foo) const MyBar = defineCustomElement(Bar) export { MyFoo, MyBar } export function register() { customElements.define('my-foo', MyFoo) customElements.define('my-bar', MyBar) } ```

Custom element library consumer usage

A consumer can use elements in a Vue file: ```vue <script setup> import { register } from 'path/to/elements.js' register() </script> <template> <my-foo ...> <my-bar ...></my-bar> </my-foo> </template> ``` Or in other frameworks with JSX and custom names: ```jsx import { MyFoo, MyBar } from 'path/to/elements.js' customElements.define('some-foo', MyFoo) customElements.define('some-bar', MyBar) export function MyComponent() { return <> <some-foo ... > <some-bar ... ></some-bar> </some-foo> </> } ```

Type checking Vue custom elements in templates

Custom elements registered globally won't have type inference in Vue templates by default. To provide type support, register global component typings by augmenting the GlobalComponents interface. For custom elements created with Vue, use the component type (not the element class) in the GlobalComponents interface: ```typescript import { defineCustomElement } from 'vue' import SomeComponent from './src/components/SomeComponent.ce.vue' export const SomeElement = defineCustomElement(SomeComponent) customElements.define('some-element', SomeElement) declare module 'vue' { interface GlobalComponents { 'some-element': typeof SomeComponent } } ```

Type checking non-Vue custom elements

For custom elements not built with Vue, define typed JS properties, events, and a type helper to register type definitions in Vue. The DefineCustomElement type helper combines element properties with global HTML props and Vue special props into a $props type, and maps events to Vue's $emit format. Custom element authors should not automatically export framework-specific type definitions; users should import the framework-specific type definition file they need.

Web Components vs Vue Components trade-offs

Custom Elements and Vue Components have feature overlap but Web Components APIs are low-level and bare-bones. Building applications requires additional capabilities not covered by the platform: declarative and efficient templating, reactive state management for cross-component logic extraction, and performant SSR/hydration. Vue's component model is designed with these needs as a coherent system. Vue SSR compiles to string concatenation when possible, much more efficient than custom elements' typical DOM simulation approach. With competent engineering, equivalent functionality could be built on Custom Elements, but this requires taking on long-term maintenance burden of an in-house framework.

Custom element limitations in component composition

Eager slot evaluation in custom elements hinders component composition. Vue's scoped slots are a powerful composition mechanism that cannot be supported by custom elements due to native slots' eager nature. Eager slots mean the receiving component cannot control when or whether to render slot content.

Custom element CSS scoping limitations

Shipping custom elements with shadow DOM scoped CSS currently requires embedding CSS inside JavaScript so it can be injected into shadow roots at runtime. This results in duplicated styles in markup in SSR scenarios. Platform features are being worked on but are not yet universally supported and have production performance/SSR concerns. Vue SFCs provide CSS scoping mechanisms that support extracting styles into plain CSS files.

SFC as custom element with .ce.vue extension

defineCustomElement works with Vue Single-File Components. To use an SFC as a custom element, end the component file name with .ce.vue. This activates custom element mode in official SFC tooling (requires @vitejs/plugin-vue@^1.4.0 or vue-loader@^16.5.0), which inlines <style> tags as strings of CSS and exposes them under the component's styles option. This will be picked up by defineCustomElement and injected into the element's shadow root when instantiated.

Custom element events are native CustomEvents

Events emitted via this.$emit or setup emit are dispatched as native CustomEvents on the custom element. Additional event arguments (payload) are exposed as an array on the CustomEvent object's detail property.

Give your agent this brain