Vue comes with it's own unique levels of scope, in addition to what Javascript has already.
Scope controls what variables can be used and where. It controls how "visible" they are to different parts of the application.
Understanding the differences between the levels of scope that Vue gives you will help you to write clearer code.
These are the 4 unique levels of scope:
Let's explore what these scopes are.
Global scope in a Vue application is like global scope in any programming language — these variables are available anywhere in the application.
You can also think of this scope as app scope, because it scopes the variable to the entire application.
The main technique for using global scope is to add a value to the Vue prototype:
Vue.prototype.$globalValue = 'Global Scope!';
By adding it to the prototype of the Vue
object, it's automatically available on every single component in our application. You can access it directly off of the component like this:
export default {mounted() {console.log(this.$globalValue); // 'Global Scope!'},};
It's a standard practice to prefix these variables with a $
, so we know that they are global values and not unique to each component.
Vue, vue-router
, and vuex
(and many other libraries) all use this technique to define global values. For example, the $route
object from vue-router
is a globally scoped variable like this.
You can also use Vuex or any other state management system to create global scope.
Most of the time global scope is a bit of a sledgehammer, and you need something a little more precise.
The next level of scope is sub-tree scope, where a variable is scoped to a specific part of the application instead of the whole thing.
This level of scope is probably the least used, but is extremely handy when you do need to use it. Oftentimes a group of components need to share a lot of the same data, and passing it through props gets very tedious.
This scope is best used to share contextual information that can change based on where a component is in the application. This can be things like:
Input
components in a registration form should require validation, but you don't want to require validation in the whole application.Sub-tree scope is created by using provide
and inject
. You provide the values you want to be available to the entire sub-tree, and then inject them into the components that need them.
In fact, being able to scope this way is the main reason that these two features exist.
A little more specific, component scope makes a variable available to a single component.
But this shouldn't be confused with the more specific instance scope.
If a variable has component scope, it is a single variable that's available to all instances of a component. You can have several of the same component, and they'll all be able to access the same variable.
You may be familiar with this as module scope in Javascript. Anything defined in a single module — or file — is all in the same module scope. Since a component is defined in a single file, everything in the component is in the same module scope.
To use component scope we need to define a variable in the same file as our component:
<template><div class="new-component">{{ componentScope }}</div></template><script>const componentScope = 'This is in the component scope';export default {data() {return {componentScope: componentScope,};},};</script>
The variable componentScope
that gets rendered in this component is the same variable, no matter how many times this component is used. There aren't multiple copies of componentScope
.
If one instance of this component modifies the value of componentScope
, it will change for every single other instance of this component. This shouldn't be used to communicate between this components, but it is a good way of sharing data.
On to our final level of scope!
Instance scope is the most specific form of Vue scope you can get.
Any variable that has instance scope is only available to a specific usage of the component. We often refer to this as internal state or sometimes local state.
Whenever you use the data()
function or use computed props, you're using instance scope.
Even adding properties directly to the component instance can get you this effect:
someMethod() {this.newProperty = 'Instance scope';}
But if you add properties this way, you have to remember that they won't be reactive.