Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Magic "this" & its Properties

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

The best and worst part of Vue is its magic. We know that if you update a data key, Vue somehow knows that it needs to re-render. That's why we can play with data in the Vue dev tools and the HTML automatically updates.

We even know that if we pass that data as a prop to another component, Vue knows to re-render that one too! We can see this on the Catalog component: it has a legend data... there it is... which we pass to the legend-component as the title prop. When we update the legend data inside Catalog, it updates the title prop and re-renders that component.

console.log(this)

But... the magic I want to talk about is not this re-rendering stuff. I love that part! The real magic of Vue is the Vue instance, the this variable. Let's take a few minutes to dive into the this variable. I promise, it will go a long way to helping us truly master Vue.

Let's play around in the Sidebar component. Add a new option called created, which is a function. We're going to talk more about this later, but basically, if you add an option called created to any component, Vue will automatically call that function when your instance is being created. We're going to use this as an easy way to dig into the this variable: console.log(this).

... lines 1 - 43
<script>
export default {
... lines 46 - 61
created() {
console.log(this);
},
... lines 65 - 69
};
</script>
... lines 72 - 86

Let's go check it out! On my console... there it is! But I'll refresh anyways just to clear things out. Cool! It's a VueComponent: an object with... a ton of properties. If you're using Vue 3, instead of VueComponent, you'll see something called a Proxy. I'll talk about what a "Proxy" is in a few minutes. For now, if you're using Vue 3, click the "Target" property to see the real object.

The Properties of this

Ok, so this is an object with a bunch of properties... and the vast majority of these are things that you will never need to worry about. If a property starts with a $, you're technically allowed to use it, but you probably won't need to except in advanced situations. If a property starts with _, then it's meant to be internal and should not be used. In Vue 3, all of the internal keys live below a property called _.

Oh! But check this out: the object also has a property called categories and another called collapsed! Woh! Those are the keys we have in data! That explains why we can reference this.collapsed: the this variable really does have a collapsed property! And if you look back at the log, the instance also has a method called toggleCollapsed. This is here because, under the methods option, we added one with that name.

Before we talk more about this, let's try one more thing. Right now, the sidebar doesn't have any props. Let's temporarily add one. Say props: and create one called testProp with type: String. One of the other things you can do here is give a prop a default value in case it's not passed to the component. Set this to a misspelled version of "I am the default value".

... lines 1 - 44
export default {
... lines 46 - 61
props: {
testProp: {
type: String,
default: 'I am the default value',
},
},
... lines 68 - 75
};
... lines 77 - 92

Perfecto-ish. Back on the browser, our code was already updated and... if we scroll down on the console... here's the latest log. Inside... yes! It now has a property called testProp!

How the "this" Object is Created

Here's the big picture. We configure Vue by passing it a set of options, like name, data, created, props and methods. Behind the scenes, Vue takes these options and creates a Vue object - the object that's in the console. When it does that, it takes all of the keys from data, all of the keys from props and all of our methods and adds those to the instance! This is why we can say this.collapsed to reference the collapsed data or this.testProp to reference that prop. Heck, we can even say this.toggleCollapsed()! Our methods become real methods on the object.

So the first thing I want you to understand is exactly this: Vue reads our options and uses them to create a Vue object where data, props and methods are real keys on that object. Later, we'll see one more option - called computed properties - that are added to the object in the same way.

Variables in the Template are called on this

Now that we understand this, we can demystify how the template works. In a template, we know that we can magically reference categories because categories is in data. Or we can magically reference toggleCollapsed because that's a key under methods.

But in reality, whenever you reference a variable or call a method in a template, Vue, sort of, prefixes it with this.. So the @click is really this.toggleCollapsed and when we're referencing collapsed, it's really this.collapsed.

Back on our browser... if you scroll down on the log, the object has a property called _uid. On Vue 3, it's _.uid. This is an internal, unique identifier for the component that we normally don't care about. But technically, because the instance has a property called _uid, we should, in theory, be able to say {{ _uid }} to print it. If I'm telling the truth about Vue, this should call this._uid on the object.

<template>
... lines 2 - 5
<h5 class="text-center">
Categories
{{ _uid }}
</h5>
... lines 10 - 42
</template>
... lines 44 - 93

And... it does! It prints "7"! Well, the value was 6 before, but when it re-rendered, _uid was 7.

Let's try something else: print definitelyNotARealProperty. Back on the browser... the error is wonderful:

... lines 1 - 5
<h5 class="text-center">
Categories
{{ definitelyNotARealProperty }}
</h5>
... lines 10 - 93

Property or method definitelyNotARealProperty is not defined on the instance but was referenced during render.

Vue is literally saying: this is not a property on the instance! And the way you add something to the instance is by defining it under data, props, methods or the computed option that we'll talk about later. I love it!

Next, Vue has one other piece of magic I want to explore called reactivity. It's all about how Vue is smart enough to re-render a template at the instant that we change a simple piece of data.

Leave a comment!

2
Login or Register to join the conversation

I really can't find this "target" key (I'm using Vue 3).

Reply

Hey, Julien! Do you see anything in the console when you add the
console.log(this);? (notice Vue 3 is backwards
compatible with Vue 2 life-cycle functions, so you can add a
create() function to the component object, but
also notice that the this object does not exist
in setup()!) In the console, you should see an
object called Proxi. Once you click on it, it has 2 properties: Target
and Handler. Click on Target to view the component's properties.

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

This course is also built to work with Vue 3!

What JavaScript libraries does this tutorial use?

// package.json
{
    "devDependencies": {
        "@symfony/webpack-encore": "^0.30.0", // 0.30.2
        "axios": "^0.19.2", // 0.19.2
        "bootstrap": "^4.4.1", // 4.5.0
        "core-js": "^3.0.0", // 3.6.5
        "eslint": "^6.7.2", // 6.8.0
        "eslint-config-airbnb-base": "^14.0.0", // 14.1.0
        "eslint-plugin-import": "^2.19.1", // 2.20.2
        "eslint-plugin-vue": "^6.0.1", // 6.2.2
        "regenerator-runtime": "^0.13.2", // 0.13.5
        "sass": "^1.29.0", // 1.29.0
        "sass-loader": "^8.0.0", // 8.0.2
        "vue": "^2.6.11", // 2.6.11
        "vue-loader": "^15.9.1", // 15.9.2
        "vue-template-compiler": "^2.6.11", // 2.6.11
        "webpack-notifier": "^1.6.0" // 1.8.0
    }
}
userVoice