Consider this basic example where we have an input and a p that shows the value of the input:
const App = {
data() {
return {
message: "hello world!"
};
}
};
Vue.createApp(App).mount('#root');
<script src="https://unpkg.com/vue@next"></script>
<div id="root">
<input v-model="message"/>
{{ message }}
</div>
When you change the input text it is reflected in the content of the p. But if you replace data() with setup(), the changes to input are no longer reflected in p:
const App = {
setup() {
return {
message: "hello world!"
};
}
};
Vue.createApp(App).mount('#root');
<script src="https://unpkg.com/vue@next"></script>
<div id="root">
<input v-model="message"/>
{{ message }}
</div>
A simple fix is to ref the message:
const App = {
setup() {
const message = Vue.ref("hello world!");
return {
message
};
}
};
Vue.createApp(App).mount('#root');
<script src="https://unpkg.com/vue@next"></script>
<div id="root">
<input v-model="message"/>
{{ message }}
</div>
But why we have to do it? Why it doesn't work out of the box?
I thought it might be because the object returned from data() is made reactive internally but the object returned from setup() doesn't because that object might contain not only data but also methods that don't need to be observed but when I check inputEl.__vueParentComponent.setupState I see that it's a Proxy. So, why it doesn't work?
return {...}just exposes that values to the outside of setup function, you should always usereforreactiveto make your data reactive :You could see the comment here that says
// expose to template:And according to setup usage with template :
Conclusion
the object returned in
setupfunction is different than that return fromdataproperty in option api