У меня есть родительское приложение с двумя дочерними компонентами.
- Дочерний компонент A (
manager-tab
) переключает свойство данных в родительском приложении, отправляя событие. - Свойство data связано с реквизитом в дочернем компоненте B (
manager-modal
). - Когда это свойство данных переключается, открывается
manager-modal
. - Нажатие «Отправить» на
manager-modal
затем предполагает закрытие модального окна.
Проблема в том, что единственный способ, которым я смог иметь такое поведение, - это напрямую мутировать опору, которая переключается из-за испущенного события manager-tab
.Это вызывает предупреждение консоли, и это то, что я хотел бы решить.Предупреждение:
view.app.php
<div id="app">
<div class="app">
<div class="app__container">
<div class="app__row">
<?php foreach ($member->rms as $rm): ?>
<manager-tab
:name="'<?= $rm->name; ?>'"
:position="'RM'"
:thumbnail="'<?= $rm->headshot ?>'"
v-on:activate-rm-modal="activateRmModal"
></manager-tab>
<?php endforeach; ?>
<?php foreach ($member->ams as $am): ?>
<manager-tab
:name="'<?= $am->name; ?>'"
:position="'AM'"
:thumbnail="'<?= $am->headshot ?>'"
v-on:activate-am-modal="activateAmModal"
></manager-tab>
<?php endforeach; ?>
</div>
</div>
</div>
<manager-modal
:is-active="showRmModal"
:phone="'<?= $rm->phone ?>'"
:full-name="'<?= $rm->fullName; ?>'"
:email="'<?= $rm->email; ?>'"
:position="'RM'"
:thumbnail="'<?= $rm->headshot ?>'"
></manager-modal>
<manager-modal
:is-active="showAmModal"
:phone="'<?= $am->phone ?>'"
:full-name="'<?= $am->fullName; ?>'"
:email="'<?= $am->email; ?>'"
:position="'AM'"
:thumbnail="'<?= $am->headshot ?>'"
></manager-modal>
</div>
view.app.js:
import Vue from 'vue';
import ManagerTab from '../vue-components/app/Manager_Tab.vue';
import ManagerModal from '../vue-components/app/Manager_Modal.vue';
window.App = new Vue({
el: '#app',
components: {
ManagerTab,
ManagerModal
},
data: {
showRmModal: false,
showAmModal: false,
},
methods: {
activateRmModal: function() {
this.showRmModal = true;
this.showAmModal = false;
},
activateAmModal: function() {
this.showAmModal = true;
this.showRmModal = false;
},
},
});
Manager_Tab.vue:
<template>
<div class="manager-tab" @click="emit">
<img :src="this.thumbnail" class="manager-tab__thumbnail" />
<div class="manager-tab__identity">
<h5 class="identity__position">
{{ this.position }}
</h5>
<h5 class="identity__name">
{{ this.name }}
</h5>
</div>
<div class="manager-tab__icon">
<i class="fa fa-chevron-right"></i>
</div>
</div>
</template>
<script>
export default {
name: 'manager-tab',
data() {
return {
}
},
props: {
name : '',
phone : '',
fullName : '',
email : '',
position : '',
thumbnail : ''
},
methods: {
emit: function() {
if (this.position == "RM") {
this.$emit('activate-rm-modal');
} else {
this.$emit('activate-am-modal');
}
}
},
}
</script>
Manager_Modal.vue:
<template>
<div :class="{ 'modal-open' : isActive }" class="modal in" v-show="isActive">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal__header">
<img class="modal__profile-pic" :src="this.thumbnail" />
<div class="modal__contact-name">{{ this.name }}</div>
<div class="modal__contact-position">{{ this.position }}</div>
<div class="modal__contact-row">
<div class="modal__contact-phone">{{ this.phone }}</div>
<div class="modal__contact-separator">|</div>
<div class="modal__contact-email">{{ this.email }}</div>
</div>
</div>
<div class="modal-body">
<textarea class="modal__comment-block" placeholder="Send a message..." v-model="text"></textarea>
</div>
<div class="modal__footer">
<div class="modal__send-btn" @click="sendMessage()">Send</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Axios from 'axios';
export default {
name: 'manager-modal',
data() {
return {
isModalOpen: this.isActive,
msg: '',
personName: '',
personPhone: '',
personMessage: '',
}
},
props: {
phone : '',
fullName : '',
email : '',
position : '',
thumbnail : '',
isActive : false
},
methods: {
sendMessage: function() {
if (this.text) {
this.personMessage = this.text;
this.close();
} else {
console.error('No message text');
}
},
close: function() {
this.isActive = !this.isActive;
},
},
}
</script>
<style lang="scss" scoped>
@import '../../../../scss/utilities/_index.scss';
.modal-open {
display: block;
}
</style>
Я пытался присвоить значение isActive
в Manager_Modal.vue свойству данных и использовать его для моих мутаций.
Это не сработало, и я думаю, что причина не сработала в том, что isActive
изначально передается из родительского приложения.
Я пытался сделать то же самое с вычисляемым свойством, но это также не работает.Я сделал это, имея такой фрагмент кода в Manager_Modal.vue, как показано ниже:
computed: {
isModalActive: function() {
this.isActive = !this.isActive;
}
}
Мое окончательное решение до того, как прийти сюда в SO, было попытка отправить еще одно событие родителю для переключения соответствующего флага (showRmModal
или showAmModal
), но родитель по какой-то причине не поймает событие.В vue devtools событие сработало, но родитель никогда его не поймает.
Я знаю, что решение этого вопроса прямо передо мной, но я просто не вижу его.Любая помощь будет принята с благодарностью.
JSFiddle: http://jsfiddle.net/eywraw8t/380816/
Вот несколько ссылок, по которым я прошел, прежде чем написать новый вопрос:
Какдинамическое добавление функций vue js в jquery
Шаблон проектирования веб-компонентов
Vue 2 - Мутирующие реквизиты vue-warn
Повторное использование модального режима с VueJS 2 <- это годичный вопрос, идентичный моему, но на него нет ответа, и мне не нравится копать старые темы, особенно когда для них нет решения. </p>
https://vuejs.org/v2/guide/components.html
https://laracasts.com/discuss/channels/vue/avoid-mutating-a-prop-directly-since-the-value-will-be-overwritten-whenever-the-parent-component-re-renders