简体   繁体   中英

Create a custom conditional render directive in Vue.js

I'm trying to work out how I can make a custom Vue conditional directive. I know I could just write a global method and call it inside a v-if, but for code clarity I'd like to have a custom directive.

The aim is to decorate an element with the directive and pass a Guid to it (it's all for handling conditional rednering depending on user permissions): v-permission="'4ECE1FD4-4019-4CA2-AB9E-0A555CCBDB5B'"

At the moment, I just add display: none to the element in the directive's bind method and this is fine for hiding the content but it would be better performance wise if the element was never rendered.

Any ideas how I can achieve this?

Current directive code is as follows:

import Vue from 'vue'

Vue.directive('permission', {
  bind: function (el, binding, vnode) {
    if (binding.value) {
      let hasPermission = 
vnode.context.$store.getters.hasApiPermission(binding.value)
      if (!hasPermission) {
        el.style.display = 'none'
      }
    } else {
      console.error('You must specify a permission ID')
    }
  }
})

Well it is possible using inserted hook:

inserted : called when the bound element has been inserted into its parent node.

example code snip:

Vue.directive('permission', {
  inserted: function (el, binding, vnode) {
    if (binding.value) {
      let hasPermission = 
vnode.context.$store.getters.hasApiPermission(binding.value)
      if (!hasPermission) {
        el.parentNode.removeChild(el)
      }
    } else {
      console.error('You must specify a permission ID')
    }
  }
})

However, it is still much more better to use the built-in v-if directive. Since Vue 2 is base on virtual DOM it will never render if the statement returns false . In this custom directive case it will be rendered firstly and removed afterwards.

I'm not sure if it is possible to achieve what you want. But I'm also not sure if it is really necessary. I think that construction like this, ...

<tag v-if="getPerm('4ECE1FD4-4019-4CA2-AB9E-0A555CCBDB5B')">
  ...
</tag>

... is really declarative enough.

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