【问题标题】:How do I open and close a modal programmatically using Vue.js?如何使用 Vue.js 以编程方式打开和关闭模式?
【发布时间】:2020-05-27 23:30:02
【问题描述】:

我已经阅读了无数关于如何使用 jquery 执行此操作的帖子,但 Vue.js 嫉妒地拥有和管理 dom,因此我需要一个使用标准 Vue.js 组件或库的解决方案。

到目前为止,我已经找到了几个我称之为“按钮事件驱动”解决方案的示例,但我需要以编程方式处理模式的打开和关闭。

问题/设计要求:当公共用户尝试与我的应用程序上的诱人按钮或其他功能进行交互时,他们尚未登录,我希望以编程方式启动模式对话框以然后让他们登录。

成功后,我需要以编程方式关闭相同的对话模式。或者,当然,他们可以选择取消并以公共用户身份继续浏览,但无法执行这些功能。

其他有用信息:我使用的是 bootstrap 4.4.1

【问题讨论】:

    标签: vue.js modal-dialog bootstrap-modal


    【解决方案1】:

    您可以使用 watch 属性。如果用户未以login=false 身份登录,则显示模式。

    // register modal component
    Vue.component("modal", {
      template: "#modal-template"
    });
    
    // start app
    new Vue({
      el: "#app",
      data: {
        showModal: false,
        login: null
      },
      created() {
        this.login = false;
      },
      watch: {
        "login": function(val) {
          this.showModal = !val;
        }
      }
    });
    .modal-mask {
      position: fixed;
      z-index: 9998;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0, 0, 0, 0.5);
      display: table;
      transition: opacity 0.3s ease;
    }
    
    .modal-wrapper {
      display: table-cell;
      vertical-align: middle;
    }
    
    .modal-container {
      width: 300px;
      margin: 0px auto;
      padding: 20px 30px;
      background-color: #fff;
      border-radius: 2px;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
      transition: all 0.3s ease;
      font-family: Helvetica, Arial, sans-serif;
    }
    
    .modal-header h3 {
      margin-top: 0;
      color: #42b983;
    }
    
    .modal-body {
      margin: 20px 0;
    }
    
    .modal-default-button {
      float: right;
    }
    
    
    /*
     * The following styles are auto-applied to elements with
     * transition="modal" when their visibility is toggled
     * by Vue.js.
     *
     * You can easily play with the modal transition by editing
     * these styles.
     */
    
    .modal-enter {
      opacity: 0;
    }
    
    .modal-leave-active {
      opacity: 0;
    }
    
    .modal-enter .modal-container,
    .modal-leave-active .modal-container {
      -webkit-transform: scale(1.1);
      transform: scale(1.1);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <!DOCTYPE html>
    <html>
    
    <head>
      <title>Modal Component</title>
      <link rel="stylesheet" type="text/css" href="/style.css" />
      <!-- template for the modal component -->
      <script type="text/x-template" id="modal-template">
        <transition name="modal">
          <div class="modal-mask">
            <div class="modal-wrapper">
              <div class="modal-container">
    
                <div class="modal-header">
                  <slot name="header">
                    default header
                  </slot>
                </div>
    
                <div class="modal-body">
                  <slot name="body">
                    default body
                  </slot>
                </div>
    
                <div class="modal-footer">
                  <slot name="footer">
                    default footer
                    <button class="modal-default-button" @click="$emit('close')">
                        OK
                      </button>
                  </slot>
                </div>
              </div>
            </div>
          </div>
        </transition>
      </script>
    </head>
    
    <body>
      <!-- app -->
      <div id="app">
        <!-- use the modal component, pass in the prop -->
        <modal v-if="showModal" @close="showModal = false">
          <!--
          you can use custom content here to overwrite
          default content
        -->
          <h3 slot="header">custom header</h3>
        </modal>
      </div>
    
    
    </body>
    
    </html>

    【讨论】:

    • 为一个努力的答案投赞成票;但是,正如我所指出的,我能够解决它。我am 在我的解决方案中使用了观察者,因此您的方法确实 可以按照您的指示工作。我的主要问题实际上是如何使用特定于 Vue.js 的方法以编程方式打开和关闭模式,我发现并成功地为我的目的定制了这种方法。不过感谢您的回答,因为我相信它可能会对其他人有所帮助!
    【解决方案2】:

    我能够使用带有(相对)最近示例的项目来构建它。这是组件,以及使用该组件的“Tester.vue”视图:

    LoginModal.vue:

     <template>
      <transition name="modal-fade">
        <div class="modal-backdrop">
          <div
            class="modal"
            role="dialog"
            aria-labelledby="modalTitle"
            aria-describedby="modalDescription"
          >
            <header class="modal-header" id="modalTitle">
              <slot name="header">
                &nbsp;
              </slot>
            </header>
            <section class="modal-body" id="modalDescription">
              <slot name="body">
               Your Login Form Goes Here
                    <button type="button" v-on:click="validateLoginForm">
                      Log In
                    </button>
                    <button type="button" @click="close" aria-label="Close modal">
                      Cancel
                    </button>
              </slot>
            </section>
            <footer class="modal-footer">
              <slot name="footer"> </slot>
            </footer>
          </div>
        </div>
      </transition>
    </template>
    
    <script>
    export default {
      name: "loginModal",
    
      data() {
        return {
          loginValidationAlerts: [],
        };
      },
    
      methods: {
        close() {
          this.$emit("close");
        },
    
        validateLoginForm() {
    //Login Form Validations go here
        },
    
        clearAllLoginValidationErrors() {
          this.loginValidationAlerts = [];
        },
    
        attemptLogin() {
        // Your login code
        },
      },
    };
    </script>
    
    <style>
    .modal-fade-enter,
    .modal-fade-leave-active {
      opacity: 0;
    }
    
    .modal-fade-enter-active,
    .modal-fade-leave-active {
      transition: opacity 0.5s ease;
    }
    
    .modal-backdrop {
      position: fixed;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      background-color: rgba(0, 0, 0, 0.3);
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    .modal {
      background: #ffffff;
      box-shadow: 2px 2px 20px 1px;
      overflow-x: auto;
      display: flex;
      flex-direction: column;
    }
    
    .modal-header,
    .modal-footer {
      padding: 15px;
      display: flex;
    }
    
    .modal-header {
      border-bottom: 1px solid #eeeeee;
      color: #4aae9b;
      justify-content: space-between;
    }
    
    .modal-footer {
      border-top: 1px solid #eeeeee;
      justify-content: flex-end;
    }
    
    .modal-body {
      position: relative;
      padding: 20px 10px;
    }
    
    .btn-close {
      border: none;
      font-size: 20px;
      padding: 20px;
      cursor: pointer;
      font-weight: bold;
      color: #4aae9b;
      background: transparent;
    }
    
    .btn-green {
      color: white;
      background: #4aae9b;
      border: 1px solid #4aae9b;
      border-radius: 2px;
    }
    </style>
    

    Tester.vue:

    <template>
      <div>
        Test Page
        <div>
          <button type="button" class="btn" @click="showModal">
            Open Modal!
          </button>
        </div>
        <div>
          <LoginModal v-show="isModalVisible" @close="closeModal"></LoginModal>
        </div>
      </div>
    </template>
    
    <script>
    import LoginModal from "@/components/LoginModal.vue";
    export default {
      components: {
        // eslint-disable-next-line vue/no-unused-components
    
        LoginModal,
      },
      data() {
        return {
          isModalVisible: false,
        };
      },
      methods: {
        showModal() {
          // Do something here to determine
          // if you should show modal
          this.isModalVisible = true;
        },
        closeModal() {
          // this will catch the close event
          // after you're done processing the login in the component
          this.isModalVisible = false;
        },
      },
    };
    </script>
    
    <style scoped></style>
    

    视图及其组件的外观非常粗糙,没有太多的格式,但你明白了。

    希望这可以帮助其他人,如果他们正在寻找 Vue 中的直接模式;我相信它必须是一个非常常见的设计要求,这种方法对我有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多