Could you explain the difference between declaring variables in different ways. When I should use these ways of declaring?
<script>
const someVariable = 12345
export default {
name: 'App',
}
</script>
<script>
export default {
name: 'App',
data() {
return {
someVariable: 12345
}
}
}
</script>
CodePudding user response:
In the first one, you can't use the someVariable
in your template
<script>
const someVariable = 12345
export default {
name: 'App',
}
</script>
<template> <p> {{someVariable}} </p> </template> //doesn't work
Available in Vue3:
to make it work you can add a setup
keyword in your script but you have to wrap your variable value with ref(...)
or reactive(...)
if you want to make it reactive to changes More info
<script setup>
const someVariable = 12345
export default {
name: 'App',
}
</script>
<template> <p> {{someVariable}} </p> </template> //works (you can see the data)
CodePudding user response:
A typical Single File Component will be like so:
<template>
...
</template>
<script>
...
</script>
- If you define a variable outside the
export
statement, it is just a plain javascript variable that you can use anywhere inside the script tag. It is not bound to the component, or related to Vue in any way. Pros:- Your variable exists in the entire
<script>
element's scope. - You can use it inside inner functions that don't have a binding to
this
.
- Your variable exists in the entire
- If you define a variable inside data function, or to put it more accurately, define a property for component instance's data object, then it is bound to the component, and hence available inside the
<template>
tags. Pros:- The variable can be referenced from
<template>
- You can take advantage of Vue's reactivity. You can define computed properties on this variable. When you use it in the template, the html is updated to reflect any change in this variable.
- You can pass it as props to child components.
- You can debug things easily using Vue devtools, you can watch changes to your variable. You can also log the variable into console like
$vm.data.someVarData
, i.e. the variable is added to the Vue component's instance.
- The variable can be referenced from
<template>
<div>
<div :class="someVarData"/> <!-- This is Ok -->
<div :class="someVar"/> <!-- This is not Ok -->
</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 Ok
console.log(this.someVarData); // This is not Ok
});
},
beforeRouteEnter() { // <--- Vue-router's Navigation guard
console.log(someVar); // This is Ok
console.log(this.someVarData); // This is not Ok
},
</script>
As such you should avoid defining variables outside export since they make it harder to understand the flow of your code. There's almost always some way you can redesign your approach to not use variables outside export.
For e.g. in the above example, you can still use your data variable inside the mounted
hook and the navigation guard with some changes:
mounted() {
const el = document.getElementById('myId');
el.addEventListener('mouseenter', () => {
console.log(someVar); // This is Ok
console.log(this.someVarData); // Ok - works because we change the function to arrow function, so it is bound to the instance's `this`
});
el.addEventListener('mouseenter', function () {
console.log(someVar); // This is Ok
console.log(this.someVarData); // Ok - works because we have manually bound the function to the instance's `this`
}.bind(this));
},
beforeRouteEnter(to, from, next) { // <--- Vue-router's Navigation guard
console.log(someVar); // This is Ok
console.log(this.someVarData); // This is not Ok
next((vm) => {
console.log(vm.someVarData); // Ok - Navigation guard's next function provides the instance's context as a callback parameter
});
},