SoFunction
Updated on 2025-04-04

Detailed explanation of basic usage of Vue components

Vue Component Overview

Component is one of the most powerful features. Components can extend HTML elements and encapsulate reusable code. According to project requirements, abstract some components, each component contains presentation, functions and styles. Each page uses different components to splice the pages according to your needs. This development model makes front-end pages easy to expand, have high flexibility, and also enables decoupling between components.

In Vue, a component is essentially a Vue instance with predefined options

A component is a custom element or a module that includes the required templates, logic, and styles. In HTML templates, components exist in the form of a custom tag, serving as placeholders. After the declarative rendering is passed, the placeholder will be replaced with the actual content

Here is a simplest example of the module

<div >
  <xiaohuochai></xiaohuochai>
</div>

Vue Registration Components

Component registration includes global registration and local registration.

Global registration

To register a global component, you can use (tagName, options)

('my-component', {
 // Options})

After the component is registered, it can be used as a custom element <my-component></my-component> in the module of the parent instance.

[Note] Make sure that the component is registered before initializing the root instance

&lt;div &gt;
 &lt;my-component&gt;&lt;/my-component&gt;
&lt;/div&gt;
&lt;script&gt;
// register('my-component', {
 template: '&lt;div&gt;A custom component!&lt;/div&gt;'
})
// Create a root instancenew Vue({
 el: '#example'
})
&lt;/script&gt;

Local registration

By using the component instance option components registration, you can make a component available only in the scope of another instance/component

&lt;div &gt;
 &lt;my-component&gt;&lt;/my-component&gt;
&lt;/div&gt;
&lt;script&gt;
// registervar Child = {
 template: '&lt;div&gt;A custom component!&lt;/div&gt;'
};
// Create a root instancenew Vue({
 el: '#example',
  components: {
  // <my-component> will only be available in the parent template  'my-component': Child
 } 
})
&lt;/script&gt;

Component Tree

Use component instance option components registration to achieve the effect of component tree

&lt;div &gt;
 &lt;my-component&gt;&lt;/my-component&gt;
&lt;/div&gt;
&lt;script&gt;
// registervar headerTitle = {
  template: '<p>I am the title</p>',
};
var headerContent = {
  template: '<p>I am content</p>',
};
var header = {
 template: `
   &lt;div class="hd"&gt;
      &lt;header-content&gt;&lt;/header-content&gt;
      &lt;header-title&gt;&lt;/header-title&gt;
   &lt;/div&gt;
 `,
  components: {
  'header-content': headerContent,
  'header-title': headerTitle
 }  
};
// Create an instancenew Vue({
 el: '#example',
  components: {
  'my-component': header
 } 
})
&lt;/script&gt;

For large applications, it is necessary to divide the entire application into components so that development can be managed. The general component application template is as follows

<div >
 <app-nav></app-nav>
 <app-view>
  <app-sidebar></app-sidebar>
  <app-content></app-content>
 </app-view>
</div>

v-once

Although rendering HTML in Vue is fast, when the component contains a lot of static content, you can consider using v-once to cache the rendering results.

('my-component', {
 template: '<div v-once>hello world!...</div>'
})

 

Template separation of Vue components

In component registration, it is more troublesome to splice HTML elements in the template option, which also leads to high coupling between HTML and JS. Thankfully, there are two ways to separate HTML templates defined in JS

script

Use the text/x-template type in the script tag and specify an id

<script type="text/x-template" >
 <p>Hello hello hello</p>
</script>
('hello-world', {
 template: '#hello-world-template'
})

The above code is equivalent to

('hello-world', {
 template: '<p>Hello hello hello</p>'
})

Here is a simple example

<div >
 <my-component></my-component>
</div>
<script type="text/x-template" >
 <div>hello world!</div> 
</script>
<script>
('my-component', {
 template: '#hello-world-template'
})
new Vue({
 el: '#example'
})
</script>

template

If you use the <template> tag, you do not need to specify the type attribute

&lt;div &gt;
 &lt;my-component&gt;&lt;/my-component&gt;
&lt;/div&gt;
&lt;template &gt;
 &lt;div&gt;hello world!&lt;/div&gt; 
&lt;/template&gt;
&lt;script&gt;
// register('my-component', {
 template: '#hello-world-template'
})
// Create a root instancenew Vue({
 el: '#example'
})
&lt;/script&gt;

 

Naming convention for Vue components

For component naming, the W3C specification is lowercase letters and contains a midscore (-). Although Vue does not require it, it is best to follow the specification.

&lt;!-- existHTMLAlways used in templates kebab-case --&gt;
&lt;kebab-cased-component&gt;&lt;/kebab-cased-component&gt;
&lt;camel-cased-component&gt;&lt;/camel-cased-component&gt;
&lt;pascal-cased-component&gt;&lt;/pascal-cased-component&gt;

When registering components, you can use any of these three types: medium marking, small hump, and large hump.

// In component definitioncomponents: {
 // Register with the medium marking 'kebab-cased-component': { /* ... */ },
 // Register with small camel 'camelCasedComponent': { /* ... */ },
 // Register with Big Hump 'PascalCasedComponent': { /* ... */ }
}

 

Vue component nesting restrictions

Not all elements can be nested with templates because they are restricted by HTML element nesting rules, especially <ul>, <ol>, <table>, <select>, which limit elements that can be wrapped, and some elements like <option> can only appear inside some other elements.

[Note] Detailed nesting rules about HTML tags are moved here

Using these restricted elements in custom components can cause some problems, e.g.

<table >
 <my-row>...</my-row>
</table>

Custom component <my-row> is considered invalid content, so it will cause errors when rendering

&lt;script&gt;
// registervar header = {
 template: '&lt;div class="hd"&gt;I'm the title&lt;/div&gt;' 
};
// Create an instancenew Vue({
 el: '#example',
  components: {
  'my-row': header
 } 
})
&lt;/script&gt;

is attribute

The workaround is to use special is attributes

&lt;table &gt;
 &lt;tr is="my-row"&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;script&gt;
// registervar header = {
 template: '&lt;div class="hd"&gt;I'm the title&lt;/div&gt;'
};
// Create an instancenew Vue({
 el: '#example',
  components: {
  'my-row': header
 } 
})
&lt;/script&gt;

 

The root element of the Vue component

Vue forces each Vue instance (component is essentially a Vue instance) to have a root element

As shown below, an error will be reported

&lt;div &gt;
 &lt;my-component&gt;&lt;/my-component&gt;
&lt;/div&gt;
&lt;script&gt;
// register('my-component', {
 template: `
  &lt;p&gt;The first paragraph&lt;/p&gt;
  &lt;p&gt;Paragraph 2&lt;/p&gt;
 `,
})
// Create a root instancenew Vue({
 el: '#example'
})
&lt;/script&gt;

Need to be rewritten as follows

&lt;script&gt;
// register('my-component', {
 template: `
  &lt;div&gt;
   &lt;p&gt;The first paragraph&lt;/p&gt;
   &lt;p&gt;Paragraph 2&lt;/p&gt;
  &lt;/div&gt; 
 `,
})
// Create a root instancenew Vue({
 el: '#example'
})
&lt;/script&gt;

 

Vue component data delivery

Generally, in Vue instance object or Vue component object, we pass data through data.

&lt;div &gt;
 &lt;my-component&gt;&lt;/my-component&gt;
 &lt;my-component&gt;&lt;/my-component&gt;
 &lt;my-component&gt;&lt;/my-component&gt;
&lt;/div&gt;
&lt;script&gt;
// register('my-component', {
 template: '&lt;div&gt;{{message}}&lt;/div&gt;',
 data:{
   message: 'hello'
 }
})
// Create a root instancenew Vue({
 el: '#example'
})
&lt;/script&gt;

Running the above code will stop Vue from executing and issue an error message on the console telling you that data must be a function in the component.

You can use the following method to bypass Vue's error prompts

&lt;script&gt;
// registervar data = {counter: 0}
('my-component', {
 template: '&lt;button v-on:click="counter += 1"&gt;{{ counter }}&lt;/button&gt;',
 data:function(){
   return data;
 }
})
// Create a root instancenew Vue({
 el: '#example'
})
&lt;/script&gt;

Since these three components share the same data, adding a counter affects all components

When a component is defined, data needs to be declared as a function that returns an initial data object, because the component may be used to create multiple instances. If data is still a pure object, all instances will share references to the same data object. By providing the data function, each time a new instance is created, the data function can be called, thus returning a brand new copy of the data object of the initial data

Therefore, this problem can be solved by returning a brand new data object for each component:

&lt;script&gt;
// register('my-component', {
 template: '&lt;button v-on:click="counter += 1"&gt;{{ counter }}&lt;/button&gt;',
 data:function(){
   return {counter: 0};
 }
})
// Create a root instancenew Vue({
 el: '#example'
})
&lt;/script&gt;

Now each counter has its own internal state

 

Vue component native events

Sometimes, you may want to listen for a native event on the root element of a component. Directly using the v-bind directive will not take effect

&lt;div &gt;
 &lt;my-component @click="doTheThing"&gt;&lt;/my-component&gt;
 &lt;p&gt;{{message}}&lt;/p&gt;
&lt;/div&gt;
&lt;script&gt;
('my-component', {
 template: '<button>button</button>',
})
new Vue({
 el: '#example',
 data:{
  message:0
 },
 methods:{
  doTheThing(){
   ++;
  }
 }
})
&lt;/script&gt;

You can use .native to modify the v-on command

&lt;div &gt;
 &lt;my-component @="doTheThing"&gt;&lt;/my-component&gt;
 &lt;p&gt;{{message}}&lt;/p&gt;
&lt;/div&gt;
&lt;script&gt;
('my-component', {
 template: '<button>button</button>',
})
new Vue({
 el: '#example',
 data:{
  message:0
 },
 methods:{
  doTheThing(){
   ++;
  }
 }
})

For more information about how to use Vue components, please click the relevant link below