Vue中的动态可重用模式

时间:2018-09-19 21:44:29

标签: javascript vue.js vuejs2

我有一个带有两个子组件的父应用程序。

  • 子组件A(manager-tab)通过发出事件在父应用程序中切换数据属性。
  • 数据属性绑定到子组件B(manager-modal)中的prop。
  • 切换该数据属性时,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>

我尝试将Manager_Modal.vue中的isActive的值分配给数据属性,并将其用于我的突变。

那没有用,我认为没用的原因是因为isActive最初是如何从父应用程序传入的。

我已经尝试对计算属性进行基本相同的操作,但这也不起作用。我是通过在Manager_Modal.vue中使用如下代码片段来做到这一点的:

computed: {
    isModalActive: function() {
        this.isActive = !this.isActive;
    }
}

在来到这里之前,我最后尝试的解决方案是尝试将另一个事件发回给父级以切换各自的标志(showRmModalshowAmModal),但父级不会捕获该事件一些理由。在vue devtools中触发了该事件,但永远不会被父级捕获。

我知道解决方案就在我眼前,但是我只是看不到它。任何帮助将不胜感激。

JSFiddle:http://jsfiddle.net/eywraw8t/380816/

在写一个新问题之前,我经过了一些链接:

How to add vue js functions to jquery dynamically

Web Components Design Pattern

Vue 2 - Mutating props vue-warn

Reuse Modal with VueJS 2 <-这是一个与我的问题相同的古老问题,但是它没有答案,而且我不喜欢挖掘旧的线程,尤其是当它们没有解决方案时。

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

0 个答案:

没有答案