An example of a standard Single File Component looks like this:
<template>
...
</template>
<script>
...
</script>
- When you declare a variable outside the
export
statement, it functions as a regular JavaScript variable that is accessible anywhere within the script tag. It is not tied to the component or Vue in any way.
Advantages:
- The variable exists within the scope of the entire
<script>
element.
- You can utilize it in inner functions without needing a binding to
this
.
- If you define a variable inside the data function, essentially creating a property for the component instance's data object, then it becomes associated with the component and thus usable within the
<template>
tags.
Advantages:
- The variable can be accessed from
<template>
.
- You can leverage Vue's reactivity by defining computed properties for this variable. Any changes to the variable are automatically reflected in the HTML template.
- You can pass it as props to child components.
- Easier debugging using Vue devtools, allowing you to monitor changes to the variable. You can also log the variable in the console like
$vm.data.someVarData
, indicating that the variable has been added to the Vue component's instance.
<template>
<div>
<div :class="someVarData"/> <!-- This is correct -->
<div :class="someVar"/> <!-- This is incorrect -->
</div>
<template>
<script>
const someVar = "blah";
export default {
data() {
return {
someVarData: "blahData",
};
},
mounted() {
const el = document.getElementById('myId');
el.addEventListener('mouseenter', function () {
console.log(someVar); // This is correct
console.log(this.someVarData); // This is incorrect
});
},
beforeRouteEnter() {
console.log(someVar); // This is correct
console.log(this.someVarData); // This is incorrect
},
</script>
It is best practice to avoid defining variables outside of export since it can complicate understanding the code flow. There is usually a way to redesign your approach to avoid using variables outside of export.
For instance, in the above scenario, you can still access your data variable within the mounted
hook and the navigation guard with some modifications:
mounted() {
const el = document.getElementById('myId');
el.addEventListener('mouseenter', () => {
console.log(someVar); // This is correct
console.log(this.someVarData); // Works because we changed the function to an arrow function, ensuring it is bound to the instance's `this`
});
el.addEventListener('mouseenter', function () {
console.log(someVar); // This is correct
console.log(this.someVarData); // Works because we manually bound the function to the instance's `this`
}.bind(this));
},
beforeRouteEnter(to, from, next) {
console.log(someVar); // This is correct
console.log(this.someVarData); // This is incorrect
next((vm) => {
console.log(vm.someVarData); // Works - Navigation guard's next function provides the instance's context as a callback parameter
});
},