Components allow us to break down the UI into independent, reusable pieces and look at each piece in isolation. It is common for an application to be organized in a tree structure of nested components:
This is very similar to how we nest native HTML elements, but Vue implements its own component model, allowing us to encapsulate custom content and logic within each component. Vue also works well with native web components. If you are curious about the relationship between Vue components and native web components,read more here.
Defining a component#
When using a build step, we usually define each Vue component in a dedicated file with the.vue
extension - known assingle file component(SFC for short):
ver
<script>export template { Dice() { Returns {tell: 0 } }}</script><model> <Knopf@Clique="tell++">you clicked me{{tell}}mal.</Knopf></model>
ver
<script set up>import { Ref } von 'ver'arttell= Ref(0)</script><model> <Knopf@Clique="tell++">you clicked me{{tell}}mal.</Knopf></model>
If no build step is used, a Vue component can be defined as a simple JavaScript object containing Vue-specific options:
js
export template { Dice() { Returns {tell: 0 } }, model: `<button @click="count++">You clicked on me {{ count }} times.</button>`}
js
import { Ref } von 'ver'export template { set up() { art tell = Ref(0) Returns { tell } }, model: `<button @click="count++">You clicked on me {{ count }} times.</button>` // oder `template: '#my-template-element'`}
The template is embedded here as a JavaScript string that Vue compiles on the fly. You can also use an ID selector pointing to an element (usually native<model>
elements) - Vue uses your content as a model source.
The example above defines a single component and exports it as a standard export of a.js
File, but you can use named exports to export multiple components from the same file.
Use of a component#
TOP
For the rest of this guide we'll use SFC syntax - the concepts around components are the same whether you use a build step or not. theexamplesThe section shows component usage in both scenarios.
To use a child component, we need to import it into the parent component. Suppose we place our counter component in a file namedButtonCounter.vue
, the component is exposed as a standard file export:
ver
<script>importButtonCountervon './ButtonCounter.vue'export template { components: {ButtonCounter }}</script><model> <h1>Here is a child component!</h1> <ButtonCounter/></model>
To make the imported component accessible to our model, we needregistrationthis with thecomponents
Possibility. The component will be available as a tag using the key under which it is registered.
ver
<script set up>importButtonCountervon './ButtonCounter.vue'</script><model> <h1>Here is a child component!</h1> <ButtonCounter/></model>
Come on<script configuration>
, the imported components are automatically made available to the model.
It is also possible to register a component globally and make it available to all components of a specific application without having to import it. The advantages and disadvantages of global versus local registration are discussed incomponent registrationSection.
Components can be reused any number of times:
model
<h1>There are many child components here!</h1><ButtonCounter/><ButtonCounter/><ButtonCounter/>
Experiments are not a playground
Experiments are not a playground
Notice that when you click the buttons, each one keeps its own separate onetell
. Because every time you use a component, a new oneexamplethat turns into.
Recommended for use on SFCsPascalCaseGenericName
Tag names for child components to distinguish them from native HTML elements. While native HTML tag names are not case-sensitive, Vue SFC is a compiled format so we can use case-sensitive tag names in it. we can also use/>
to close a tag.
If you build your models directly in a DOM (e.g. as the content of a native<model>
element), the template is subject to the browser's native HTML parsing behavior. In these cases, you must useKebab-Fall
and explicit closing tags for components:
model
<!-- if this model is written in the DOM --><Counter button></Counter button><Counter button></Counter button><Counter button></Counter button>
VerDOM model analysis caveatsfor more details.
passing props#
When we create a blog, we probably need a component that represents a blog post. We want all blog posts to have the same visual layout but with different content. Such a component is only useful if you can pass data to it, such as: B. Title and content of the specific post we want to display. That's where props come in.
Props are custom attributes that you can register with a component. To pass a title to our blog post component, we need to declare it in the list of props accepted by that component, using thepropspossibilitydefinePropsmacro:
ver
<!-- BlogPost.vue --><script>export template { props:['title']}</script><model> <h4>{{title}}</h4></model>
When a value is passed to a prop attribute, it becomes a property of that component instance. The value of this property can be accessed from both the model and the component.is
Context, just like any other component property.
ver
<!-- BlogPost.vue --><script set up>defineProps(['title'])</script><model> <h4>{{title}}</h4></model>
defineProps
is a compile-time macro available only within<script configuration>
and does not have to be imported explicitly. Declared props are automatically made available to the model.defineProps
It also returns an object containing any props passed to the component, so we can access them in JavaScript if we need to:
js
artprops= defineProps(['title'])console.registration(Props.Title)
Also see:Enter components
If you don't use<script configuration>
, props must be declared using the methodprops
option, and the props object is passedfurnish ()
As the first argument:
js
export template { props:['title'], set up(props) { console.registration(props.title) }}
A component can have any number of props, and by default, any value can be passed to any prop.
Once a prop is registered, you can pass data to it as a custom attribute, like this:
model
<blog entry title="My journey with Vue"/><blog entry title="Blogging with a view"/><blog entry title="Why Vue is so much fun"/>
However, in a typical application, you probably have a number of posts in your parent component:
js
export template { // ... Dice() { Returns {posts:[ {I would go: 1,title: 'My journey with Vue' }, {I would go: 2,title: 'Blogging with a view' }, {I would go: 3,title: 'Why Vue is so much fun' }] } }}
js
artposts= Ref([ { I would go: 1, title: 'My journey with Vue' }, { I would go: 2, title: 'Blogging with a view' }, { I would go: 3, title: 'Why Vue is so much fun' }])
Then for each you want to render a component by usingv-para
:
model
<blog entry v-para="to postnoposts":key="to post.I would go":title="to post.title"/>
Experiments are not a playground
Experiments are not a playground
note howv-bind
used to pass dynamic prop values. This is especially useful when you don't know in advance the exact content you will be rendering.
That's all you need to know about props for now, but once you've finished reading this page and feel comfortable with its content, we encourage you to come back later for the full guideprops.
hear events#
As we develop ours<blog post>
Component, some functions may require backup communication with parent component. For example, we might decide to build in an accessibility feature to enlarge the text of blog posts and leave the rest of the page at its default size.
In the parent we can support this function by adding apostFontSize
ownership of dataRef:
js
Dice(){ Returns {posts:[ /* ... */],postFontSize: 1 }}
js
artposts= Ref([ /* ... */])artpostFontSize= Ref(1)
What can be used in template to control font size of all blog posts:
model
<div:Style="{font size:postFontSize+'em'}"> <blog entry v-para="to postnoposts":key="to post.I would go":title="to post.title"/></div>
Now let's add a button<blog post>
Component Model:
ver
<!-- BlogPost.vue, omitting <script> --><model> <div Class="blog entry"> <h4>{{title}}</h4> <Knopf>enlarge text</Knopf> </div></model>
The button still doesn't do anything - we want to click the button to tell the parent to increment the text of all posts. To solve this problem, the components provide a custom events system. The parent can choose to listen to each event on the child component instancein
or@
, just like a native DOM event:
model
<blog entry...@extended text="postFontSize+=0,1"/>
Then the child component can raise an event for itself by calling the built-in methodthe $emit method, passing the event name:
ver
<!-- BlogPost.vue, omitting <script> --><model> <div Class="blog entry"> <h4>{{title}}</h4> <Knopf@Clique="$output('extended text')">enlarge text</Knopf> </div></model>
Thanks to@enlarge-text="postFontSize += 0,1"
The listener receives the event and updates the value of the parentpostFontSize
.
Experiments are not a playground
Experiments are not a playground
We can optionally declare events that are emitted with the methodoutputpossibilityDefine emissionsmacro:
ver
<!-- BlogPost.vue --><script>export template { props:['title'], output:['extended text']}</script>
ver
<!-- BlogPost.vue --><script set up>defineProps(['title'])Define emissions(['extended text'])</script>
This documents all events that a component sends and is optionalvalidates them. Also, Vue can avoid applying them implicitly as native listeners on the child component's root element.
samedefineProps
,Define emissions
can only be used in<script configuration>
and does not need to be imported. It returns aoutput
function equivalent to$output
Method. It can be used to dump events on the<script configuration>
Section of a component where$output
is not directly accessible:
ver
<script set up>artoutput= Define emissions(['extended text'])output('extended text')</script>
Also see:Outputs input component
If you don't use<script configuration>
, you can declare emitted events using the methodoutput
Possibility. You can access theoutput
Function as a property of the configuration context (passed tofurnish ()
as second argument):
js
export template { output:['extended text'], set up(props, ctx) { ctx.output('extended text') }}
That's all you need to know about custom component events for now, but once you've finished reading this page and feel comfortable with its content, we encourage you to come back later for the full guidecustom events.
Content distribution with slots#
As with HTML elements, it's often useful to be able to pass content to a component like this:
model
<AlertBox>Something bad happened.</AlertBox>
What could look something like this:
This is a demonstration error.
Something bad happened.
This can be achieved with Vue's custom<space>
Element:
ver
<model> <div Class="Warnfeld"> <Strength>This is a demonstration error.</Strength> <Slot/> </div></model><Style limited>.Warnfeld { /* ... */}</Style>
As you will see above, we use the<space>
as a placeholder for where the content should go - and that's it. have been realised!
Experiments are not a playground
Experiments are not a playground
That's all you need to know about slots for now, but once you've finished reading this page and feel comfortable with its content, we encourage you to come back later for the full guidekey.
Dynamic Components#
Sometimes it is useful to dynamically switch between components, e.g. B. in a tabbed interface:
Open example in playground
Open example in playground
The above is possible thanks to Vue's<Components>
element with something specialit is
Attribute:
model
<!-- component changes when currentTab changes --><Components:it is="currentTab"></Components>
model
<!-- component changes when currentTab changes --><Components:it is="Führer[currentTab]"></Components>
In the example above, the value passed to:It is
may contain:
- the name string of a registered component, OR
- the actual imported component object
You can also use theit is
-Attribute to create regular HTML elements.
When switching between multiple components with<Component :is="...">
, a component is unmounted at shutdown. We can force inactive components to stay "alive" with the built-in onesKomponente <KeepAlive>.
DOM model analysis caveats#
If you write your Vue templates directly into the DOM, Vue needs to get the template string from the DOM. This raises some caveats due to browsers' native HTML parsing behavior.
TOP
Note that the limitations described below only apply if you write your models directly in the DOM. They do NOT apply when using string templates from the following sources:
- individual file components
- Inline model strings (e.g.
Model: '...'
) <script type="text/x-template">
case sensitive#
HTML tags and attribute names are not case-sensitive, so browsers interpret all uppercase letters as lowercase. This means that when using in-DOM models, PascalCase component names and camelCased property names orin
All event names must use their kebab equivalents (hyphen separated):
js
// camelCase in JavaScriptartblog entry= { props:['postTitle'], output:['updatePost'], model: `<h3>{{ Beitragstitel }}</h3> `}
model
<!-- kebab-case in HTML --><blog entry post title="Hallo!"@update post="onUpdatePost"></blog entry>
self-sealing labels#
We used self-closing tags for components in earlier code examples:
model
<mycomponent/>
This is because Vue's model parser respects/>
as a hint to terminate any tag, regardless of its type.
However, in DOM models, we always need to include explicit closing tags:
model
<my-component></my-component>
This is because the HTML specification only allowssome specific itemsomitting the closing tags, which is the most common<Enter>
e<Bild>
. If you omit the closing tag from all other elements, the native HTML parser assumes that you never closed the opening tag. For example the following snippet:
model
<my-component/> <!-- we intend to close the tag here... --><Period>Hallo</Period>
is parsed as:
model
<my-component> <Period>Hallo</Period></my-component> <!-- but the browser closes it here. -->
Element placement restrictions#
Some HTML elements, such as<ul>
,<ol>
,<table>
e<select>
have restrictions on what elements can appear in them, and like some elements<li>
,<tr>
, z<Option>
can only appear inside some other elements.
This causes problems when using components with elements that have such restrictions. For example:
model
<Tisch> <blog post row></blog post row></Tisch>
the custom component<blog-post-row>
is hoisted as invalid content and causes errors in the eventual rendered output. We can use something specialis attributeals Workaround:
model
<Tisch> <tr it is="vue:blog-post-row"></tr></Tisch>
TOP
When used in native HTML elements, the value ofit is
must be precededver:
to be interpreted as a Vue component. This is necessary to avoid confusion with the nativecustom built-in elements.
For now, that's all you need to know about the caveats of parsing DOM models - and indeed the demise of Vueessential. congratulations! There's more to learn, but first we recommend taking a break to play around with Vue yourself - create something fun or check out some of theexamplesif you haven't already.
Once you're comfortable with the knowledge you've just digested, continue with the guide to learn about the components in more detail.