If you have used Vue.js for any amount of time, or even read over the Hello World examples, you’ve probably wondered why on earth properties like “data” need to be functions, or why everything is declared in separate blocks, but mounted to the component at runtime. Well, here’s your explanation.
— Sorry to interrupt this program! 📺
If you're interested in learning Vue in a comprehensive and structured way, I highly recommend you try The Vue.js Master Class course by Vue School. Learning from a premium resource like that is a serious investment in yourself.
Plus, this is an affiliate link, so if you purchase the course you help Alligator.io continue to exist at the same time! 🙏
It turns out there is a very clear set of reasons for all of this. For one thing, Vue components are largely static! Yep! A component declaration, including its methods, property definitions, and computed properties, are shared between all instances of that component in the app. When Vue needs to run methods against a specific instance of a component, it apply()s them to get the the proper object as this.
Reason: Saving Memory
Many frameworks, such as Angular 2 or, (at times) React, make each instance of a component a separate object. Angular 2  being the extreme case where every component is an instance of a class. This means that everything each component needs is initialized for every component. Normally though, you really only need to keep a component’s data separate for each initialization. Methods and such stay the same.
Vue avoids that pitfall by having data be a function that returns an object. That allows separate components to have separate internal state without needing to fully re-instantiate the entire component. Methods, computed property definitions, and lifecycle hooks are created and stored only once, and run against every instance of a component.
Reason: Static Components
Vue 2 fully embraces the idea of fast, lightweight static components. These have no internal state or data, and are generally rendered once or only on external state changes. This allows such functional components to be incredibly fast.
To take advantage of such features, you can use v-once in your templates to render a property only once, or declare your component to be functional with functional: true in the component definition.
It is often noticed by people new to Vue that while you declare your component state in data, computed properties in computed, methods in methods, they are all accessed on this.thing instead of this.type.thing (eg. this.myMethod() instead of this.methods.myMethod().)
This, again, is because your component definition really is just a definition. The actual component your methods run in is different. Vue needs those computed, methods, props, and data definitions to be able to know how to assemble the component, but for convenience it maps them to the root of the component instead of those properties.
As a side note, you can actually access this.$data.prop, this.$methods.method(), at runtime, but this is not recommended.
Hopefully this article helps clear the matter up for you. :)