How can i re-use a function across multiple directive hooks?

629 views Asked by At

I have a directive that updates how an elements looks when its content changes. As such, I need it to run both when its native change event fires, and when the element is first set up. So I run my function in the bind hook, and in the componentUpdated hook.

So the structure of that looks something like this:

directives: {
    demo: {
        bind(el) {
            el.addEventListener('change', () => {
                alert('i am a directive function');
            });
        },

        componentUpdated(el) {
            alert('i am a directive function');
        }
    }
}

It works fine, but i had to copy and paste the function in both hook declarations, and i would like to get rid of that.

I thought maybe a directive declaration could have its local properties, accessible through this, so i tried to solve it like so:

directives: {
    demo: {
        myFunction: () => {
            alert('i am a directive function');
        },

        bind(el) {
            el.addEventListener('keyup', () => this.myFunction());
        },

        componentUpdated(el) {
            this.myFunction();
        }
    }
}

But that didn't work, saying this.myFunction is not a function.

How would I make this work?

1

There are 1 answers

1
tony19 On BEST ANSWER

Option 1: Separate directive variable

Define the directive in its own variable that could be referenced by name instead of this:

// MyComponent.vue
const myDirective = {
  myFunction(msg) {
    console.log(msg)
  },
  bind(el, { value }) {
    el.addEventListener('keyup', () => myDirective.myFunction(value))
  },
  componentUpdated(el, { value }) {
    myDirective.myFunction(value)
  }
}

export default {
  directives: {
    myDirective
  }
}

demo 1

Option 2: Separate function

Define the common function externally from the directive, and use where needed:

// MyComponent.vue
function myFunction(msg) {
  console.log(msg)
}

export default {
  directives: {
    myDirective: {
      bind(el, { value }) {
        el.addEventListener('keyup', () => myFunction(value))
      },
      componentUpdated(el, { value }) {
        myFunction(value)
      }
    }
  }
}

demo 2

In both examples above, the directives could be moved to their own file, which would increase their testability and improve the readability of the component.