How to prevent/stop propagation of default event (

2019-04-09 14:07发布

Vue.directive('login-to-click', {
  bind (el) {
    const clickHandler = (event) => {
      event.preventDefault()
      event.stopImmediatePropagation()
      alert('click')
    }
    el.addEventListener('click', clickHandler, true)
  }
})

usage

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

handleClick is always triggered. How I can prevent that from directive? Tried with/without addEventListener "capture" flag without any luck.


For now I ended up with following solution:

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

And then in component

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

标签: vue.js vuejs2
4条回答
Luminary・发光体
2楼-- · 2019-04-09 14:50

You can use:

event.target.preventDefault();

I am not sure why would want to do that though, since you are adding a click listener for a reason.

Perhaps you could clarify your question a bit more.

查看更多
霸刀☆藐视天下
3楼-- · 2019-04-09 15:01

In my case, I need to conditionally prevent the default behavior of the right and left arrow keys. While the cursor is in the middle of my input field, I want the normal behavior of the event to move the cursor. However, when I reach the beginning or end of the input I want the focus to change to the next input and position the cursor at the beginning of the next field for a right arrow and at the end of the next field for a left arrow. When I position the cursor at the beginning or end of the next field the default left or right event behavior gives me a "one off" effect. This occurs because the left or right arrow key event can finish it's default behavior after I change the focus and set the cursor location.

In my case "event.target.preventDefault()" didn't stop the default behavior. I used "event.preventDefault()" to prevent the default behavior of the event:

<template>
  <div>
    <input
      @keydown.right.stop="right($event)"
    >
    <!--
      other inputs are defined here
    --> 
  </div>
</template>

<script type="text/javascript">
export default {
  methods: {
    right (event) {
      /*
        code to conditionally change input element focus goes here
      */
      // prevent default behavior
      event.preventDefault()
    }
  }
}
</script>
查看更多
SAY GOODBYE
4楼-- · 2019-04-09 15:11

From my understanding those are two different event handlers, you are only preventing the default event of the one bound in the directive, this has no influence on @click however, because you are not overwriting the click listener but adding a second one. If you want the default of your @click binding to be prevented you can use @click.prevent="handleClick".

I don't think there's any way to do it from the directive, since you explicitly add another listener by binding @click to the button.

查看更多
做个烂人
5楼-- · 2019-04-09 15:12

in my app I have many buttons (follow/like/add to watchlist/block etc) that require user to be logged in to click on them

As with many things in Vue 2, this is a bad use case for a directive, but a very good use case for a component.

Here is a button that is only clickable when the user is authorized.

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>

With this button you can set an authorized handler and a non-authorized handler. Additionally, you can just disable the button if the user is not authorized.

In this component the authorized state is passed in through a property, but if you were using some form of state management (like Vuex) you could just as easily use that instead.

查看更多
登录 后发表回答