template option - string template for component
The template option accepts a string that defines the component's template. A template provided via the template option will be compiled on-the-fly at runtime. It is only supported when using a build of Vue that includes the template compiler. The template compiler is NOT included in Vue builds that have the word 'runtime' in their names, such as vue.runtime.esm-bundler.js. If the string starts with '#' it will be used as a querySelector and the selected element's innerHTML will be used as the template string. This allows the source template to be authored using native template elements. If the render option is also present in the same component, template will be ignored. If the root component of your application doesn't have a template or render option specified, Vue will try to use the innerHTML of the mounted element as the template instead.
template option type signature
The template option has type interface ComponentOptions { template?: string }
render option - programmatic virtual DOM tree
The render option is a function that programmatically returns the virtual DOM tree of the component. It is an alternative to string templates that allows you to leverage the full programmatic power of JavaScript to declare the render output of the component. Pre-compiled templates, for example those in Single-File Components, are compiled into the render option at build time. If both render and template are present in a component, render will take higher priority.
render option type signature
The render option has type interface ComponentOptions { render?(this: ComponentPublicInstance) => VNodeChild }. VNodeChild is defined as type VNodeChild = VNodeChildAtom | VNodeArrayChildren. VNodeChildAtom is defined as type VNodeChildAtom = VNode | string | number | boolean | null | undefined | void. VNodeArrayChildren is defined as type VNodeArrayChildren = (VNodeArrayChildren | VNodeChildAtom)[].
compilerOptions - configure runtime compiler for template
The compilerOptions option configures runtime compiler options for the component's template. This config option is only respected when using the full build, such as the standalone vue.js that can compile templates in the browser. It supports the same options as the app-level app.config.compilerOptions and has higher priority for the current component.
compilerOptions type and fields
The compilerOptions option has type interface ComponentOptions { compilerOptions?: { isCustomElement?: (tag: string) => boolean, whitespace?: 'condense' | 'preserve' (default: 'condense'), delimiters?: [string, string] (default: ['{{', '}}']) comments?: boolean (default: false) } }
slots option - type inference for programmatic slot usage
The slots option is a TypeScript-only feature supported in Vue 3.3+. It assists with type inference when using slots programmatically in render functions. The option's runtime value is not used. The actual types should be declared via type casting using the SlotsType type helper from 'vue'. Example usage: defineComponent({ slots: Object as SlotsType<{ default: { foo: string; bar: number }, item: { data: number } }>, setup(props, { slots }) { /* slots are now typed */ } })
Scoped CSS with <style scoped> attribute
When a <style> tag has the scoped attribute, its CSS will apply to elements of the current component only. It is similar to style encapsulation found in Shadow DOM, does not require polyfills, and is achieved using PostCSS to transform selectors by adding data attributes. A scoped selector like .example becomes .example[data-v-f3f3eg9], and template elements receive corresponding data-v-f3f3eg9 attributes.
Scoped CSS child component root element styling
With scoped styles, the parent component's styles will not leak into child components. However, a child component's root node will be affected by both the parent's scoped CSS and the child's scoped CSS by design. This allows the parent to style the child root element for layout purposes.
Deep selectors with :deep() pseudo-class
To make a selector in scoped styles affect child components (go deep), use the :deep() pseudo-class. For example, .a :deep(.b) in a scoped style block will be compiled to .a[data-v-f3f3eg9] .b. DOM content created with v-html are not affected by scoped styles, but can still be styled using deep selectors.
Slotted content styling with :slotted() pseudo-class
By default, scoped styles do not affect contents rendered by <slot/>, as they are considered to be owned by the parent component passing them in. To explicitly target slot content, use the :slotted() pseudo-class, for example :slotted(div) { color: red; }.
Global selectors in scoped styles with :global()
To apply just one rule globally within scoped styles, use the :global() pseudo-class rather than creating another <style> block. For example, :global(.red) { color: red; } will apply globally even within a scoped style block.
Mixing local and global styles in same component
You can include both scoped and non-scoped <style> tags in the same component. Non-scoped styles apply globally while scoped styles apply only to the current component.
Scoped CSS performance with element selectors
Scoped styles do not eliminate the need for classes. When scoped, element selectors like p { color: red } will be many times slower when combined with attribute selectors. Using classes or ids instead, such as .example { color: red }, virtually eliminates that performance hit.
Descendant selectors in recursive components with scoped styles
Be careful with descendant selectors in recursive components when using scoped styles. For a CSS rule with selector .a .b, if the element matching .a contains a recursive child component, then all .b in that child component will be matched by the rule.
CSS Modules with <style module>
A <style module> tag is compiled as CSS Modules and exposes the resulting CSS classes to the component as an object under the key of $style. The resulting classes are hashed to avoid collision, achieving CSS scoping to the current component only.
Custom inject name for CSS Modules
You can customize the property key of the injected classes object in CSS Modules by giving the module attribute a value. For example, <style module="classes"> will expose classes via classes.red instead of $style.red.
v-bind() CSS function for dynamic component state
SFC <style> tags support linking CSS values to dynamic component state using the v-bind CSS function. This works with both Options API and <script setup>. For JavaScript expressions, they must be wrapped in quotes, for example v-bind('theme.color'). The actual value is compiled into a hashed CSS custom property, so the CSS remains static, and the custom property is applied to the component's root element via inline styles and reactively updated if the source value changes.
v-bind() in CSS with Options API example
Example of v-bind() CSS function with Options API:
```vue
<template>
<div class="text">hello</div>
</template>
<script>
export default {
data() {
return {
color: 'red'
}
}
}
</script>
<style>
.text {
color: v-bind(color);
}
</style>
```
This example shows binding a data property to CSS without quotes in the Options API pattern.
v-bind() in CSS with <script setup> example
Example of v-bind() CSS function with <script setup>:
```vue
<script setup>
import { ref } from 'vue'
const theme = ref({
color: 'red',
})
</script>
<template>
<p>hello</p>
</template>
<style scoped>
p {
color: v-bind('theme.color');
}
</style>
```
This example demonstrates using v-bind() with JavaScript expressions (wrapped in quotes) and <script setup> syntax.