【问题标题】:How to prevent/stop propagation of default event (click) in directive (vue 2.x)如何防止/停止在指令(vue 2.x)中传播默认事件(点击)
【发布时间】:2018-01-08 08:52:13
【问题描述】:
Vue.directive('login-to-click', {
  bind (el) {
    const clickHandler = (event) => {
      event.preventDefault()
      event.stopImmediatePropagation()
      alert('click')
    }
    el.addEventListener('click', clickHandler, true)
  }
})

用法

<button @click="handleClick" v-login-to-click>CLICK</button>

handleClick 总是被触发。我怎样才能防止这种指令?尝试使用/不使用 addEventListener“捕获”标志,但没有任何运气。


现在我最终得到了以下解决方案:

Vue.prototype.$checkAuth = function (handler, ...args) {
  const isLoggedIn = store.getters['session/isLoggedIn']
  if (isLoggedIn) {
    return handler.apply(this, args)
  } else {
    router.push('/login')
  }
}

然后在组件中

<button @click="$checkAuth(handleClick)">CLICK</button>

【问题讨论】:

    标签: vue.js vuejs2


    【解决方案1】:

    据我了解,这是两个不同的事件处理程序,您只是阻止了指令中绑定的一个的默认事件,这对 @click 没有影响,但是,因为您没有覆盖点击侦听器,而是添加了第二个一。 如果您希望阻止 @click 绑定的默认设置,您可以使用 @click.prevent="handleClick"

    我认为指令没有任何方法可以做到这一点,因为您通过将@click 绑定到按钮来显式添加另一个侦听器。

    【讨论】:

    • 我的用例非常简单:在我的应用程序中,我有许多按钮(关注/喜欢/添加到关注列表/阻止等),需要用户登录才能单击它们。我想添加 v-login-to-click 指令,如果用户未登录,它将阻止对给定元素/组件的任何点击(相反,我会将用户重定向到登录页面或显示登录模式)。
    • 好吧,就像我说的,你不能从一个指令覆盖你用@click 绑定的clicklistener。您唯一能做的就是在同时使用指令和@click 的任何地方使用click.prevent,或者(注意:hacky)在​​指令中使用el 引用并删除所有其他点击侦听器。我真的不认为 2) 是一个选项,因为它会在您的情况下从字面上删除 handleClick。
    【解决方案2】:

    在我的应用程序中,我有很多按钮(关注/喜欢/添加到关注列表/阻止 等)需要用户登录才能点击它们

    与 Vue 2 中的许多事情一样,这对于指令来说是一个糟糕的用例,但对于组件来说却是一个非常好的用例。

    这是一个只有在用户被授权时才能点击的按钮。

    console.clear()
    
    const AuthenticatedButton = {
      props:["onAuth", "onNonAuth", "disable", "auth"],
      template: `
        <button @click="onClick" 
                :disabled="disableWhenNotAuthorized">
          <slot>{{this.auth}}</slot>
        </button>`,
      computed:{
        disableWhenNotAuthorized(){
          return this.disable && !this.auth
        }
      },
      methods:{
        onClick(){
          if (this.auth && this.onAuth) this.onAuth()
          if (!this.auth && this.onNonAuth) this.onNonAuth()      
        }
      }
    }
    
    new Vue({
      el:"#app",
      data:{
        loggedIn: false
      },
      methods:{
        onClick(){
          alert("User is authenticated")
        },
        notAuthorized(){
          alert("You are not authorized.")
        }
      },
      components:{
        "auth-btn": AuthenticatedButton
      }
    })
    <script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
    <div id="app">
      <h3>User is {{!loggedIn ? 'Not Authorized' : 'Authorized'}}</h3>
      <auth-btn :auth="loggedIn" 
                :on-auth="onClick"
                :on-non-auth="notAuthorized">
        Executes non auth handler when not authorized
      </auth-btn> <br>
      <auth-btn :auth="loggedIn" 
                :on-auth="onClick"
                :disable="true">
        Disabled when not authorized
      </auth-btn> <br><br>
      <button @click="loggedIn = true">Authenicate User</button>
    </div>

    使用此按钮,您可以设置授权处理程序和非授权处理程序。此外,如果用户未经授权,您可以禁用该按钮。

    在这个组件中,授权状态是通过属性传递的,但如果您使用某种形式的状态管理(如 Vuex),您可以轻松地使用它。

    【讨论】:

    • 这是一个很好的例子,但假设其中一个组件不是按钮,而是链接或图像。然后我必须为他们每个人准备 sich 包装器。
    • @user606521 这实际上花了我大约 10 分钟来写。如果需要,除了模板之外的所有东西都可以是一个 mixin。您的担忧是有道理的,但感觉像是过早的优化。
    • 现在我得到了另一个解决方案(请参阅我的有问题的编辑)。我只想保持代码干净且尽可能小——我正在处理一个包含 100 多个不同页面的项目。我不确定我的解决方案是否有点“hacky”,但效果很好。
    • @user606521 绝对是,选择最适合你的 :) 我主要想指出在 Vue 2 中重用的 main 向量是组件。另一种处理这个问题的方法可能是高阶组件,它本质上是一个包装任何其他返回新组件的组件。在这种情况下,“授权”的 HOC 可能会应用于任何其他组件。这在 React 中更为常见,但在 Vue 中正在取得进展。
    【解决方案3】:

    https://vuejs.org/v2/guide/events.html#Event-Modifiers

    有几个修饰符。 .prevent 就是我要找的东西

    <a href="#" @click.prevent="sendMessage('just one click');">
    

    【讨论】:

      【解决方案4】:

      你可以使用:

      event.target.preventDefault();
      

      我不确定为什么要这样做,因为您添加点击侦听器是有原因的。

      也许您可以进一步澄清您的问题。

      【讨论】:

      • event.target.preventDefault 未定义。
      • 那么您的event 在您登录时实际显示的是什么?
      猜你喜欢
      • 2020-09-09
      • 2018-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多