Reputation: 49
I wanted my directive to work as v-if since in my directive I have to check access rights and destroy the element if it does not have access.
Here is my code
Vue.directive('access', {
inserted: function(el, binding, vnode){
//check access
if(hasAccess){
vnode.elm.parentElement.removeChild(vnode.elm);
}
},
});
vue file
<my-component v-access='{param: 'param'}'>
The issue is that i'm applying this directive to a component, it's removing the component but not the execution of functions called by the created/mounted hook.
In the component(my-component) there are functions in mounted/created hook. The execution of these functions are done and I don't want these functions to be executed. Is there a way to stop execution of the mounted/created events?
Upvotes: 2
Views: 1002
Reputation: 34286
It is impossible to replicate the behavior of v-if
in a custom directive. Directives cannot control how vnodes are rendered, they only have an effect on the DOM element it is attached to. (v-if
is special, it's not actually a directive but instead generates conditional rendering code when the template is compiled.)
Though I would avoid doing any of the following suggestions if possible, I'll provide them anyway since it's close to what you want to do.
You definitely need to use v-if
to do the conditional rendering. So all we have to do is come up with a global helper method which calculates the access permission.
Vue.prototype.$access = function (param) {
// Calculate access however you need to
// ("this" is the component instance you are calling the function on)
return ...
}
Now in your templates you can do this:
<my-component v-if="$access({ param: 'param' })">
This is basically the same as #1 except instead of polluting the Vue prototype with garbage, you define the method only on the root instance:
new Vue({
el: '#app',
render: h => h(App),
methods: {
access(param) {
return ...
}
}
})
Now in your templates you can do this:
<my-component v-if="$root.access({ param: 'param' })">
Now it's clearer where the method is defined.
This may not be ideal, but for what it's worth you can investigate the viability of a global mixin.
You can create a custom component (ideally functional but it needn't be) that can calculate access for specific regions in your template:
Vue.component('access', {
functional: true,
props: ['param'],
render(h, ctx) {
// Calculate access using props as input
const access = calculateAccess(ctx.props.param)
// Pass the access to the default scoped slot
return ctx.scopedSlots.default(access)
}
})
In your templates you can do this:
<access :param="param" v-slot="access">
<!-- You can use `access` anywhere in this section -->
<div>
<my-component v-if="access"></my-component>
</div>
</access>
Since <access>
is a functional component, it won't actually render it's own component instance. Think of it more like a function than a component.
A bit overkill for your situation, but interesting nonetheless if you ever have a more complicated scenario.
Upvotes: 5