如何拦截 bootstrap "data-target" 事件?

How can I intercept the bootstrap "data-target" event?

问题的详细说明:

我正在使用 bootstrap 模态对话,我只希望它在用户登录时工作。

虽然 vue.js 可以在用户未登录或处理任何类型的链接时使此元素完全消失,但 'data-target' 给我带来了麻烦。

目标: 在激活模式之前检查用户是否登录。如果用户未登录,我会在代码的其他地方处理它(这里的细节与 IMO 问题无关,但涉及激活一个完全独立的模式)。

如果用户已登录,则允许通过 'data-target'

激活模式

问题: 目前,当用户未登录时,'reportModalIdWithHash' 在 'checkForLogin()'

代码:

          <span
            class="float-right text-muted smaller-font make-clickable"
            data-toggle="modal"
            :data-target="reportModalIdWithHash"
            v-on:click="checkForLogin()"
          >
            Report
          </span>

关于首选解决方案的注意事项:

我希望在模式被“data-target”触发之前发生“checkForLogin()”。

虽然我总是可以使用 Vue.js 让元素消失,但我希望用户看到该选项,然后当他们点击它时,如果他们没有登录,然后 显示登录名而不是报告模式。

是否可以拦截并重新开火'data-target'?

为什么不使用动态 data-target

:data-target="`#${isLoggedIn ? 'fancy' : 'login'}-modal`"

new Vue({
  el: '#app',
  data: () => ({
    isLoggedIn: false
  }),
  methods: {
    handleLogin() {
      // replace this with an async API call...
      this.isLoggedIn = true;
      // and switch modals...
      ['fancy', 'login'].forEach(name => $(`#${name}-modal`).modal('toggle'));
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" ></script>

<div id="app" class="container">
  <div class="form-check p-3">
    <input class="form-check-input" type="checkbox" v-model="isLoggedIn" id="check">
    <label class="form-check-label" for="check">
      <code>isLoggedIn</code> (click to change)
    </label>
  </div>
  <div class="btn btn-primary"  data-toggle="modal"
       v-text="`Open Report`"
       :data-target="`#${isLoggedIn ? 'fancy' : 'login'}-modal`"></div>
  <div class="modal fade" tabindex="-1" role="dialog" id="login-modal">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title">Login modal</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">&times;</span>
          </button>
        </div>
        <div class="modal-body">
          <p>Login modal content goes here.</p>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
          <button type="button" class="btn btn-primary" @click="handleLogin" data-dismiss="modal" >Login</button>
        </div>
      </div>
    </div>
  </div>
  <div class="modal fade" tabindex="-1" role="dialog" id="fancy-modal">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title">Fancy report</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">&times;</span>
          </button>
        </div>
        <div class="modal-body">
          <p>Fancy report goes here.</p>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Meh...</button>
          <button type="button" class="btn btn-primary">OK</button>
        </div>
      </div>
    </div>
  </div>
</div>


注意:这是一个简单的概念验证,不是生产就绪代码:

  • 不要像我的示例那样使用 Vue + Bootstrap + jQuery(这很野蛮)。你最好使用 BootstrapVue(并摆脱 jQuery)。
  • 您可能想要使用单个动态模式并通过插槽注入 body、标题和页脚内容。这并不总是更好,但通常会导致 DRY-er 代码以牺牲可读性为代价。

使用 BootstrapVue,您的按钮看起来更像这样:

<b-btn v-b-modal[`${isLoggedIn ? 'fancy' : 'login'}-modal`]> Open Modal</b-btn>

...或者,如果您想在方法中处理它:

<b-btn @click="handleOpenModal">Open modal</b-btn>

和:

methods: {
  handleOpenModal() {
    this.$bvModal.open(this.isLoggedIn ? 'fancy-modal' : 'login-modal');
  }
}