Vue.js Показать вызов одного компонента из другого компонента

У меня есть 2 компонента:

Vue.component('repo-button', {
  props:["check_in_id", "repo_id"],
  template: '#repo-button',
  methods: {
    fetchRepo: function() {
        url = window.location.href.split("#")[0] + "/check_ins/" + this.check_in_id + "/repositionings/" + this.repo_id + ".json"
        cl(url)
        cl(this)
        var that;
        that = this;

        $.ajax({
            url: url,
            success: function(data) {
                cl(data)
                that.showRepo();
            }
        })

    },
    showRepo: function() {
        // what do I put here to display the modal 
    }
  },
  data: function() {
  var that = this;
  return {

  }
}
});

Vue.component('repo-modal', {
    template: "#repo-modal",
    data: function() {
        return {
            status: 'none'
        }
    }
});

var repositionings = new Vue({
    el: "#repo-vue"
});

... и мой вид состоит из кнопки и модального окна. Я хочу, чтобы кнопка вызывала fetchRepo для компонента repo-button и отображала модальное окно (изменив его свойство status с none на block.

<script type="text/x-template" id="repo-button">
    <div class='socialCircle-item success'>
    <i class='fa fa-comment' 
         @click="fetchRepo"
      :data-check_in='check_in_id' 
      :data-repo='repo_id'> 
    </i>
  </div>
</script>

<script type="text/x-template" id="repo-modal">
    <div  v-bind:style="{ display: status }" class="modal" id="vue-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" data-client_id="<%= @client.id %>">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h4 class="modal-title"></h4>
                </div>
                <div class="modal-body"></div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-danger btn-simple" data-dismiss="modal">Close</button>
                </div>
            </div>
        </div>
    </div>
</script>

<div id="repo-vue">
    <div is="repo-modal"></div>
    <div is="repo-button" repo_id="<%= ci.repositioning.id %>" check_in_id="<%= ci.id %>"></div>
</div>

person Jeremy Thomas    schedule 03.04.2017    source источник


Ответы (1)


Подпорки вниз, события вверх

В Vue.js отношения между родительскими и дочерними компонентами можно резюмировать как свойства вниз, события вверх. Родитель передает данные дочернему элементу через реквизиты, а дочерний элемент отправляет сообщения родителю через события.

В частности, если состояние компонента должно контролироваться извне (родителем или родственным компонентом), это состояние должно быть передано в качестве реквизита от родителя. События указывают родителю, что состояние должно быть изменено.

Состояние вашего модального окна контролируется событиями в себе и в родственном компоненте. Таким образом, состояние находится в родительском элементе и передается в модальное окно в качестве реквизита. Нажатие модальной кнопки «Закрыть» генерирует (настраиваемое) событие hidemodal; щелчок по значку комментария родственного компонента создает событие showmodal. Родитель обрабатывает эти события, соответствующим образом устанавливая свой элемент данных showRepoModal.

Vue.component('repo-button', {
  template: '#repo-button',
  methods: {
    showRepo: function() {
      this.$emit('showmodal');
    }
  }
});

Vue.component('repo-modal', {
  template: "#repo-modal",
  props: ["show"],
  computed: {
    status() {
      return this.show ? 'block' : 'none'
    }
  },
  methods: {
    hideRepo() {
      this.$emit('hidemodal');
    }
  }
});

var repositionings = new Vue({
  el: "#repo-vue",
  data: {
    showRepoModal: false
  }
});
.socialCircle-item i {
  cursor: pointer;
}
<link href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
<template id="repo-button">
    <div class='socialCircle-item success'>
    <i class='fa fa-comment' 
         @click="showRepo"
         >
    </i>
  </div>
</template>

<template id="repo-modal">
    <div  v-bind:style="{ display: status }" class="modal" id="vue-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" >
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h4 class="modal-title"></h4>
                </div>
                <div class="modal-body"></div>
                <div class="modal-footer">
                    <button type="button" @click="hideRepo" class="btn btn-danger btn-simple" data-dismiss="modal">Close</button>
                </div>
            </div>
        </div>
    </div>
</template>

<div id="repo-vue">
  <div is="repo-modal" :show="showRepoModal" @hidemodal="showRepoModal = false"></div>
  <div is="repo-button" @showmodal="showRepoModal = true"></div>
</div>

person Roy J    schedule 03.04.2017
comment
Это отличное объяснение, спасибо. Я должен создать для этого еще один вопрос, но если я хочу передать данные из repo-button в модальное (для модального содержимого), как мне это сделать? - person Jeremy Thomas; 04.04.2017
comment
В качестве аргумента в emit, например this.$emit('showmodal', 'some content');, и ваш обработчик событий должен быть методом (например, @showmodal="doShowModal"), который будет получать аргументы и обрабатывать их. - person Roy J; 04.04.2017