简体   繁体   English

如何使用 Vue.js 在父组件中更新的子组件中的数据?

[英]How can I use data in the child component that are updated in parent component using Vue.js?

My parent component looks like this :我的父组件如下所示:

<template>
    ...
        <PaymentMethod/>
        ...
        <b-btn class="float-right" variant="primary" @click="add">
             OK
        </b-btn>
    ...
</template>
<script>
    export default {
        ...
        methods: {
            add() {
                ...
            }
        }
    }
</script>

My child component looks like :我的子组件看起来像:

<template>
    ...
        <b-form-select v-model="selected" :options="methodOptions" />
        ...
        <b-form-select v-model="termSelected" :options="termOptions" />
    ...
</template>
<script>
    export default {
        data () {
            return {
                selected: null,
                termSelected: null
            }
        },
        ...
    }
</script>

If the add method called from parent component, I want it get data selected in the child component如果从父组件调用add方法,我希望它在子组件中选择数据

How can I do it?我该怎么做?

Use Vuex, your store.js will look like :使用 Vuex,您的 store.js 将如下所示:

 import Vue from 'vue';
 import Vuex from 'vuex';
   Vue.use(Vuex);


 const state = {
    selected: null
 };
 const mutations = {
    SET_SELECTED(state, selected) {
    state.selected =selected;
   }
   }

 export default new Vuex.Store({
    state,
   mutations
   })

in app.js :在 app.js 中:

import store from './vuex/store';
const app = new Vue({
el: '#app',
store,
...})

in parent component :在父组件中:

    <template>
     ...
   <PaymentMethod :selected="selected" />
     ...
        <b-btn class="float-right" variant="primary" @click="add">
        OK
        </b-btn>
     ...
    </template>
  <script>
   export default {
    data(){
     returen {
       selected:null    
     }
     },
    methods: {
        add() {
         ...
       this.$store.commit("SET_SELECTED",this.selected) 
      }
    }
 }
 </script>

in child component :在子组件中:

   <template>
     ...
     <b-form-select @change="selectItem" v-model="selected" 
             :options="methodOptions" />
   ...
 </template>
<script>
  export default {
   data () {
    return {
      selected:null
    }
 },
 methods:{
   selectItem(){
    this.$store.commit("SET_SELECTED",this.selected
    }
    ...
 }

One solution is to use the sync modifier along with computed getters and setters:一种解决方案是将sync修饰符与计算的 getter 和 setter 一起使用:

Parent Component父组件

<template>
    ...
        <PaymentMethod :method.sync="method" :term.sync="term"/>
        ...
        <b-btn class="float-right" variant="primary" @click="add">
             OK
        </b-btn>
    ...
</template>
<script>
    export default {
        data () {
            return {
                method: null,
                term: null
            }
        },
        ...
    }
</script>

Child Component子组件

<template>
    ...
        <b-form-select v-model="_method" :options="methodOptions" />
        ...
        <b-form-select v-model="_term" :options="termOptions" />
    ...
</template>
<script>
    export default {
        props: ['method', 'term'],
        computed: {
            _method: {
               get () {
                   return this.method
               },
               set (value) {
                   this.$emit('update:method', value)
               }
            },
            _term: {
               get () {
                   return this.term
               },
               set (value) {
                   this.$emit('update:term', value)
               }
            },
        },
        ...
    }
</script>

Now with the parent component's add method you have access to the child's selected method and term options:现在使用父组件的add方法,您可以访问子组件的选定methodterm选项:

methods: {
    add() {
        // this.method is the value of _method 
        // this.term is the value of _term
    }
}

Update更新

Since you've stated you want both the value and text of the selected term / method, I would suggest the following changes:由于您已经声明您想要所选术语/方法的值和文本,我建议进行以下更改:

Parent家长

<template>
    ...
        <PaymentMethod :methods="methods" 
                       :terms="terms"  
                       :method.sync="method" 
                       :term.sync="term"/>
        ...
        <b-btn class="float-right" variant="primary" @click="add">
             OK
        </b-btn>
    ...
</template>
<script>
    export default {
        data () {
            return {
                // define your method and term arrays in the parent component.
                // pass them as props to the child component.
                methods: [{...}, {...}, {...}],
                terms: [{...}, {...}, {...}],
                method: null,
                term: null
            }
        },
        // use computed properties to retrieve the selected method / term option.
        computed: {
            selectedMethod () {
                return this.methods.find(method => method.value === this.method)
            },
            selectedTerm () {
                return this.terms.find(term => term.value === this.term)
            },
        }
        ...
    }
</script>

Child孩子

<template>
    ...
        <b-form-select v-model="_method" :options="methods" />
        ...
        <b-form-select v-model="_term" :options="terms" />
    ...
</template>
<script>
    export default {
        props: ['method', 'term', 'methods', 'terms'],
        computed: {
            _method: {
               get () {
                   return this.method
               },
               set (value) {
                   this.$emit('update:method', value)
               }
            },
            _term: {
               get () {
                   return this.term
               },
               set (value) {
                   this.$emit('update:term', value)
               }
            },
        },
        ...
    }
</script>

The best and recommended way is using $emit最好和推荐的方法是使用 $emit
The bellow example could show you how?下面的例子可以告诉你如何? < /br> </br>

 Vue.component('child-tmp', { props: ['post'], template: ` <button @click="$emit('add-like')">Like</button> ` }) new Vue({ el: "#app", data: { posts: [{ title: "Heading goes here 1", content: "Something sadofnd idfidif disong.", likes: 0 }, { title: "Heading 2 goes here", content: "Something sadofnd idfidif disong.", likes: 0 }], totalLikes: 0 } })
 <script src="https://unpkg.com/vue"></script> <div id="app"> <h2>Posts:</h2> <section> <div v-for="post in posts"> <h2> {{post.title}} </h2> <p> {{post.content}} </p> <child-tmp v-bind:post="post" v-on:add-like="post.likes = post.likes+1"></child-tmp><span style="margin-left:10px;">{{post.likes}}</span> </div> </section> </div>

In the above snippet you could see we are using props to read the data from parent to child and we use $emit to pass the data from child and v-on:add-like to receive the emitted data.在上面的代码片段中,您可以看到我们使用 props 从父级到子级读取数据,我们使用 $emit 传递来自 child 的数据和 v-on:add-like 来接收发出的数据。

There are two ways:有两种方式:

1. You can either emit event when selecting data in child component: 1. 您可以在选择子组件中的数据时发出事件:

<template>
    ...
        <b-form-select v-model="selected" :options="methodOptions" />
    ...
</template>
<script>
    export default {
        data () {
            return {
                selected: null
            }
        },
        ...
        methods: {
          onSelect() {
            this.$emit('selectData', this.selected);
          }
        }
    }
</script>

and then handle this event in parent component:然后在父组件中处理这个事件:

<template>
    ...
        <PaymentMethod @selectData="changeChildData($event)"/>
        ...
        <b-btn class="float-right" variant="primary" @click="add">
             OK
        </b-btn>

    ...
</template>
<script>
    export default {
        ...
        data() {
            return {
              childData: null
            }
        },
        methods: {
            changeChildData(newData) {
              this.childData = newData;
            },
            add() {
                ...
            }
        }
    }
</script>

2. or you can use storage Vuex 2.或者你可以使用存储Vuex

or event bus (simplified version of Vuex):或事件总线(Vuex 的简化版):

import Vue from 'vue';
export const EventBus = new Vue();

you pass data from child to event bus您将数据从孩子传递到事件总线

<script>
    import { EventBus } from '../EventBus.js';
    export default {
        data () {
            return {
                selected: null
            }
        },
        ...
        methods: {
          onSelect() {
            EventBus.$emit('selectData', this.selected);
          }
        }
    }
</script>

and subscribe from parent for it change并从父母那里订阅它的变化

<script>
    import { EventBus } from '../EventBus.js';
    export default {
        ...
        data() {
            return {
              childData: null
            }
        },
        created() {
            EventBus.$on('selectData', (data) => {
                this.childData = data;
            });
        },
        methods: {
            add() {
                ...
            }
        }
    }
</script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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