Как я могу использовать данные в дочернем компоненте, которые обновляются в родительском компоненте с помощью Vue.js? - PullRequest
0 голосов
/ 14 сентября 2018

Мой родительский компонент выглядит так:

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

Мой дочерний компонент выглядит так:

<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>

Если метод add вызван из родительского компонента, я хочу получить данные, выбранные в дочернем компоненте

Как я могу это сделать?

Ответы [ 4 ]

0 голосов
/ 15 сентября 2018

Одним из решений является использование модификатора sync вместе с вычисленными геттерами и сеттерами:

Родительский компонент

<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>

Дочерний компонент

<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>

Теперь с помощью метода add родительского компонента у вас есть доступ к выбранным дочерним элементам method и term:

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

Обновление

Поскольку вы заявили, что хотите указать значение и текст выбранного термина / метода, я бы предложил следующие изменения:

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>

Ребенок

<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>
0 голосов
/ 14 сентября 2018

Есть два способа:

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>

, а затем обрабатывать это событие в родительском компоненте:

<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.или вы можете использовать хранилище Vuex

или шину событий (упрощенная версия Vuex):

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

вы передаете данные от дочернего элемента к шине событий

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

и подпишитесь от родителя на его изменение

<script>
    import { EventBus } from '../EventBus.js';
    export default {
        ...
        data() {
            return {
              childData: null
            }
        },
        created() {
            EventBus.$on('selectData', (data) => {
                this.childData = data;
            });
        },
        methods: {
            add() {
                ...
            }
        }
    }
</script>
0 голосов
/ 14 сентября 2018

Лучший и рекомендуемый способ - использовать $ emitПример ниже может показать вам, как?

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>

В приведенном выше фрагменте вы можете видеть, что мы используем реквизиты для чтения данных от родителя к ребенку, и мы используем $ emit для передачи данных от потомка и v-on: add-like для получения отправленных данных.

0 голосов
/ 14 сентября 2018

Используйте 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
   })

в app.js:

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

в родительском компоненте:

    <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>

в дочернем компоненте:

   <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
    }
    ...
 }

...