Ling
Ling

Reputation: 11

Vue custom directive how to receive a function as params and the function will not auto exec

How do I receive a function with params in directive like vue v-on?

<div v-example="test(id)"></div>

and this script

methods: {
    test(id) {
        console.log(id);
    }
}

the test function will auto exec, but v-on will not?

Upvotes: 1

Views: 2114

Answers (4)

Wouter Vandevelde
Wouter Vandevelde

Reputation: 904

You can simply pass a function and the parameters separately to your directive like demonstrated on this fiddle. Since passing the function like test('something') will cause it to be evaluated immediately.

Just replace the inserted hook with the one you need: https://v2.vuejs.org/v2/guide/custom-directive.html#Directive-Hook-Arguments

<div v-demo="{myFunction: test, param: 'something'}"></div>

Upvotes: 0

lsblsb
lsblsb

Reputation: 1352

You may also do the following:

<div v-example="test(id)"></div>

script:

directives: {
  'example': {
    bind(el, binding, vnode) {
      el.addEventListener(binding.arg, (e) => {
        if(binding.value instanceof Function) {
          binding.value();
        }
      })
    }
  } 
},
methods: {
  test(id) {
    let local_id = id;
    return () => {
       console.log(local_id);
    }
  }
}

Upvotes: 2

Shay Yzhakov
Shay Yzhakov

Reputation: 1123

It depends on what you are trying to achieve. If your goal is to pass the directive a function pointer (so you can execute the function later on inside your directive), you should listen to what gonnavis said and use an arrow function.

What you tried to do will not work because when Vue will mount the component, it will bind the directive to the element (<div>) and create a binding object. This object contains a "value" function which is assigned to return the argument you passed to the directive. So, while the directive is being bound, it calculates the value you passed to it, and if it is a function invocation, it invokes the function immediately.

You can imagine that when the element with your directive is bound, the following line will run:

const binding = {
  value: YOUR_ARG
}

And, in your case, it will be translated to:

const binding = {
  value: test(id)
}

Which will calculate test(id) immediately.

It is all about functional programming.

Upvotes: 0

gonnavis
gonnavis

Reputation: 356

Don't know how to mimic the built-in v-on style, there's too many problems includes auto run.

Below is the most concise and simple solution I can think of.

html

<div v-example="function(){ test(id) }"></div>

or more concise

<div v-example="()=>test(id)"></div>

js

directives:{
  example: {
    bind(el, binding){
      binding.value()
    }
  }
},
methods: {
    test(id) {
        console.log(id);
    }
}

Upvotes: 1

Related Questions