Check out the previous post What Is A Vue Instance? in this series.
Vue works on the principle of reusable visual components. Each component is a Vue instance which is nested under the root Vue instance. These instances manage and reactively render their virtual DOM to the real DOM according to changes in their state and or the state of their children.
A Vue app is a composition of components each with their own state, that is mutated according to lifecycle hooks, methods, and event listeners (more on those later). While these components can be declared in pure JavaScript, and passed HTML templates as strings, this is not the preferred way to work. Instead developers use .vue
files.
Vue's "single-file components" or .vue
files have their own scoped HTML, JavaScript and CSS that compile into Vue instances. In specific, these files have three sections (template, script and style) containing the components HTML, JavaScript and CSS, that define the Vue instance properties and are added to the virtual DOM and rendered as desired. You can see an example of a single-file component by opening App.vue
. This file might seem bit strange but we'll take it section by section.
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'app',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
The first template
section is the Vue instance's template HTML. In pure JavaScript this would be a string literal passed as a property of the options object like new Vue({ template: Hello
. It is an HTML-based template syntax that allows you to declaratively bind the rendered DOM to the underlying Vue instance's data.})
)
The script
section is where the remainder of instance properties are defined and exported for compilation. However, the App component is not doing much here besides registering a subcomponent called HelloWorld
that is bound and rendered in the template section above.
Finally, the style
section is used for defining CSS related to a component's visual appearance. It can be on a global or scoped in level which is pretty handy. Let's open the HelloWorld
component to get another look into what is going on.
HelloWorld.vue
Below is an excerpt of HelloWorld.vue
component that is rendered by App.vue.
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
// ... rest of template code
</p>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
// ... scoped css
</style>
In the template
section we can see familiar HTML elements like div
, p
, etc, in addition to an expression {{ msg }}
which is bound to the value in the Vue instance's props
or data
(depending on declaration). Let's take a look at the script section for more insight.
The script
section shows that the msg
variable is declared from props
which is data passed down by the parent component (e.g. App
). This variable is bound to the template, and renders whatever value provided by the parent component. This variable could alternatively be declared from a Vue instance's data
function instead. If you remove the props
definition, and replace it with data
as seen below, the Vue app will re-render and look exactly the same.
<script>
export default {
name: 'HelloWorld',
data() {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
So what's the difference between props
and data
? For starters, data
is a component's in-memory and private storage for values, whereas, props
is data passed from parent to child components. Both are "reactive" in that if either change, the component will re-render. However, data
is mutable storage and props
is not intended to be. That is, props
are a mechanism of one way data flow and communication from the parent to child components, and as such are not advised to mutate (if they are Vue will send a warning message to the console). Both props
and data
are linked to the rendered DOM through the Vue instance but have different utilities.