Vue.js: How to specify props in single file component?
After a long time of experiment, I found out a practical solution:
The project file structure:
src/ assets/ components/ Home.vue App.vue main.jspackage.jsonconfig.jsindex.html
Now, we want to access the root component -- App
's vm fields inside the sub-component Home.vue
, with vue-route
on.
main.js:
import Vue from 'vue'import VueRouter from 'vue-router'import App from './App'Vue.use(VueRouter);let router = new VueRouter();router.map({ '/': { name: 'home', component: require('./components/Home') }});router.start(App, 'body');
App.vue:
<template> <p>The current path: {{ $route.path }}.</p> <p>Outer-Value: {{ outer_var }}</p> <hr/> <!-- The below line is very very important --> <router-view :outer_var.sync="outer_var"></router-view></template><script> import Home from './compnents/Home.vue' export default { replace: false, components: { Home }, data: function() { return { outer_var: 'Outer Var Init Value.' } } }</script>
Home.vue
<template> <div> <p><input v-model="outer_var" /></p> <p>Inner-Value: {{ outer_var }}</p> </div></template><script> export default { // relating to the attribute define in outer <router-view> tag. props: ['outer_var'], data: function () { return { }; } }</script>
Conclusion
Note that the inner prop bound the property on the attribute of the component tag (<router-view>
Tag in this case.), NOT directly on the parent component.
So, we must manually bind the passing props field as an attribute on the component tag. See: http://vuejs.org/guide/components.html#Passing-Data-with-Props
Also, notice I used a .sync
on that attribute, because the binding is one-way-down by default: http://vuejs.org/guide/components.html#Prop-Binding-Types
You can see, sharing the status through nesting components is a bit confused. To make a better practice, we can use Vuex.
You can do it like this:
app.js
<template> <div class="hello"> <h1>{{ parentMsg }}</h1> <h1>{{ childMsg }}</h1> </div></template><script>export default { props: ['parentMessage'], data () { return { childMessage: 'Child message' } }}</script><style scoped>h1 { color: #42b983;}</style>
main.js
import Vue from 'vue'import App from './App.vue'new Vue({ el: '#app', data() { return { message: 'Parent message' } }, render(h) { return h(App, { props: { parentMessage: this.message } }) }});
Since a couple of months ago, Vue has its own styleguide for references and stuff like this. Props are one of the references, actually an essential one.
BAD
props: ['status']
Good
props: { status: String}
Even better
props: { status: { type: String, required: true, validator: function (value) { return [ 'syncing', 'synced', 'version-conflict', 'error' ].indexOf(value) !== -1 } }}
You can find more on this here