简体   繁体   中英

VueJS v-model and data binding between components

I am having troubles with how vuejs binds the data. I have a parent Vue.component which is the handles the layout of my form and i have child vue.component which handle the different input groups. I am having troubling getting the data from the child component to sync with the parent component for when i do my form submit in future.

I currently have my file like this:

var title = "";
Vue.component('create_new_entry', {
    template: '<div><div class="row"><h1 v-on:click="test()">{{title}}</h1><div class="col-md-12"><section_title></section_title></div></div></div>',
    data    : function() {
        return {
            title: title
        };
    },
});
Vue.component('section_title', {
    template: '<div><h1 v-on:click="test()">{{title}}</h1><input type="text" class="form-control" v-model="title"></div>',
    data    : function() {
        return {
            title: title
        };
    },
    methods : {
        test: function() {
            console.log(this);
        }
    }
});

I am not sure where i am going wrong and as much as i try to the documentation im still having trouble with how the data get bound and updated.

You are declaring two entirely separate fields, one in each component, and there is nothing tying them together other than they share the same name. Vue is treating those as two separate fields, when one changes, the other does not. The fields are private and internal to the component instances.

Shared state should be passed down to child components as props, and should be passed up to parent components as events. There are a few ways of approaching this, the simplest being adding a prop and event. A more complex way would be to use a state management tool like vuex. https://github.com/vuejs/vuex

Here is a simple example using a prop and an event.

Prop documentation: https://v2.vuejs.org/v2/guide/components.html#Props

Event documentation: https://v2.vuejs.org/v2/guide/components.html#Custom-Events

var title = "";
Vue.component('create_new_entry', {
    template: '<div><div class="row"><h1 v-on:click="test()">{{title}}</h1><div class="col-md-12"><section_title :title="title" @title-changed="changeTitle"></section_title></div></div></div>',
    data    : function() {
        return {
            title: title
        };
    },
    methods: {
        changeTitle(newTitle) {
            this.title = newTitle;
        }
    }
});
Vue.component('section_title', {
    template: '<div><h1 v-on:click="test()">{{title}}</h1><input type="text" class="form-control" v-model="innerTitle"></div>',
    props: ['title'],
    data    : function() {
        return {
            innerTitle: this.title
        };
    },
    methods : {
        test: function() {
            console.log(this);
        }
    },
    watch: {
        title(val){
            this.innerTitle = val;
        },
        innerTitle(val) {
            this.$emit('title-changed', val);
        }
    }
});

The parent component passes its title component down to the child component so it has access to it. The child component is unable to modify its props, so it copies the value of the prop to a local data field innerTitle . The input in the child component is bound to the innerTitle using v-model. A watch is added on the innerTitle so that any time it changes, it emits an event title-changed . The parent component listens for the title-changed event, and whenever it occurs, the parent updates its title field to that new value.

The child component also has a watch on the title prop so that if the parent's title value changes for any other reason, the child component will be able to update its internal state to match the parent's new value.

As stated before, you could also use Vuex, or use another Vue instance as a bus as explained here https://v2.vuejs.org/v2/guide/components.html#Non-Parent-Child-Communication

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM