简体   繁体   中英

Priority of Vue directives?

I used a form component of a Third Party Component Library, which hasn't disabled props, and I bind a click event to every form item via @click to popup a dialog when the form item was clicked. But here is my problem, in some case the form item should not be clickable, so I create a custom prevent-click directive which like this:

const clickHandler = e => {
  e.stopImmediatePropagation()
  e.stopPropagation()
  return false
}

const directive = {
  bind(el, { value }) {
    if (value) {
      el.addEventListener('click', clickHandler, true)
    }
  },
  update(el, { value }) {
    if (!value) {
      el.removeEventListener('click', clickHandler, true)
    } else {
     el.addEventListener('click', clickHandler, true)
    }
  }
}

used like this:

<form-item v-prevent-click="true" @click="showDialog"></form-item>

The prevent-click directive do nothing but add a captured event listener to the form-item, which stop the propagation, everything goes well so far, but the problem is that the form-item has a pseudo child element which is added by css after selector. So when I clicked the pseudo child element, due to the pseudo child element itself doesn't dispatch the click event instead of the form-item, so the form-item element will still dispatch the event, besides the vue builtin directive @click event handler was bound first, which result in the useCapture param of addEventListener method won't effect.

In the 1.x version, there is priority option of custom directive, but the 2.X remove it. So are there anyway to make my custom directive bind before than the builtin @click?

You should use Vue's built-in event modifiers (reference here ). Try this:

<form-item @click.stop.prevent="showDialog"></form-item>

I don't know what your third-party components framework is, but if you really need to handle the preventDefault by yourselft, I suggest you to do the following:

Template

<form-item @click="showDialog"></form-item>

Script

methods: {
    showDialog(e) {
        e.preventDefault();
        // Your code to display dialog...
    }
}

If you also need to pass arguments to showDialog , remember that you can - just pass the event as first argument:

<form-item @click="showDialog($event, urData)"></form-item>

Consider passing a flag to showDialog . If you cannot modify showDialog function wrap it in another function:

// Your compoennt template
<form-item @click="wrappedShowDialog(true)"></form-item>

// Vue.js component
wrappedShowDialog(isAllowed) {
    if (isAllowed) {
        this.showDialog();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM