I am reading up on Vue components, and find their explanation of why data needs to be a function somewhat confusing:
The root instance
var vm = new Vue({
el: '#example',
data: {
message: 'here data is a property'
}
})
A component
var vm = new Vue({
el: '#example',
data: function () {
return {
counter: 0
}
}
})
The Vue docs explain this difference by assigning a global counter variable to each component, and then they act surprised that each component shares that same data... Also they don't explain why they already use a function here.
var data = { counter: 0 }
Vue.component('simple-counter', {
template: '<div>{{ counter }}</div >',
data: function () {
return data
}
})
Of course the data is shared now
<simple-counter></simple-counter>
<simple-counter></simple-counter>
<simple-counter></simple-counter>
When you reference a global object as your data source, it's no surprise that the components don't have their own data. That is also true for root Vue instances that have data as a property.
var mydata = { counter: 0 }
var vm1 = new Vue({
el: '#example1',
data: mydata
})
var vm2 = new Vue({
el: '#example2',
data: mydata
})
So I'm still left with the question why a component can't have a data property?
The data option should always be a function in the context of components which returns a fresh object.
This precaution is made by vue. So whenever you define the object directly in the data option, vue will catch for making the mistake.
Components are never allowed to directly mutate its state. This prevents us from messing up and doing bad things where components do not have their own state.
If this precaution is not made by vue, then you will have a chance to mutate any other components that owns from the component and this would be a security issue.
Example from the documentation:
It’s good to understand why the rules exist though, so let’s cheat.
Since all three component instances share the same data object, incrementing one counter increments them all! Ouch. Let’s fix this by instead returning a fresh data object:
Now all our counters each have their own internal state.
From my understanding of this, It's to save memory
Many frameworks, such as Angular 2 or, (at times) React, make each instance of a component a separate object. 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.
See this
It must be a function because otherwhise the data will be shared among all instances of the component, as objects are call by reference rather than call by value. This does not only happen when you reference a global object but also when data is an object itself. If data is a factory-function that returns an object this object will be created from scratch every time you mount a new instance of the component instead of just passing a reference to the global data.