Suppose you’re developing a web app for online shopping. One page of the app lets the users to input a rating of a product. You’d like to build an interface similar to example p321.html. Wouldn’t it be great if you can utilize some existing code from a third-party library instead of writing this rating feature yourself?
Vue components allow programmers to package some functionality into reusable code, and incorporate the code into their own application with ease. Web app interface typically involves three kinds of code: HTML (the text content and structure), CSS (presentation) and JavaScript (business logic and dynamic behaviour). So Vue components are able to package HTML, CSS and JavaScript codes into a single reusable unit.
Fortunately, there are many UI component library that we can take advantage of in making our web app. And, in fact, we had silently used the Rate component of the component library Element Plus to write example p321.html.
In the code snippet from example p321.html, we register our app to use the rate component with components: { ElRate: ElementPlus.ElRate }
. In the template, we use the HTML syntax to place the component as in <el-rate v-model="value" :colors="colors"></el-rate>
. Similar to HTML elements, Vue supports attribute binding, bi-directional binding and event handling on Vue components. (More detail to be covered in coming sections.)
<div id="app">
<span>Rating: {{ value }}</span>
<el-rate v-model="value" :colors="colors"></el-rate>
</div>
<script>
const opts = {
components: { ElRate: ElementPlus.ElRate },
data() {
return {
value: 3,
colors: ['#99A9BF', '#F7BA2A', '#FF9900']
}
}
};
Vue.createApp(opts).mount('#app');
</script>
As web apps become more complicated, putting all the constituent HTML and JavaScript in one large file becomes very difficult to manage and understand. One common technique to tackle this complexity is to decompose the web app interface into a hierarchy of components, as in this diagram.
After decomposition, each component can be stored in a separate file / module. Some of the components can be developed and tested independently, and some may be reused among different pages of the web app, or even among different web apps.
In this section, we use some components from the ElementPlus Desktop UI library to illustrate common features of Vue components.
When you insert a component to a page, you often need to provide value for some properties / attributes to initialize the components. In the following example, property placeholder
of <el-input>
provides the short message shown in the input box before the user enters any data. When the value is a string literal, you don’t need to use the data-binding syntax v-bind:attr
.
However, if the value is other data types (e.g. number, boolean), a data property of the component, or a JavaScript expression, you must use the data-binding syntax.
Data-binding is uni-directional. This means that data is passed into the component in one direction only. If the value changes in the container, Vue will update the component view through reactivity.
Some components also emit event
, and the container can register an event handler with @event
. In this example, the <el-button>
emits click
event, which is handled by a method in the container.
Many input controls in a UI library needs to pass user input to the container. For this purpose, the relevant components usually support v-model
to bind a property to a value in the container in both directions. The bound component property can be of different data type. For example, dueDate
binds to modelValue
in <el-date-picker>
, and their data type is Date
.
Internally, bi-directional binding is implemented by the
update
event. Refer to online reference for more information.
Sometimes we need to distribute content to a component. For example, the label on the button <el-button>Swap the two book</el-button>
is put between the start tag and the end tag. The component <el-button>
is said to have a slot, and it displays the slot content inside the button.
The content passed into a slot is not restricted to string. In general it can contain HTML content and even other components. Consider the <el-row>
and <el-col>
components for page layout.
Some components even have more than slots. For example <el-card>
has a header slot, in addition to the default slot. Refer to online reference for more information.
In the next section, we’ll integrate the above examples into a single web app. The dist version of this app is accessible here: c37-feature.