Vue Event Handling with v-on

Jul 5, 2019

In Vue, the v-on directive is how you run JavaScript in response to DOM events. If you want to run some code when the user clicks a button, you should use v-on.

For example, suppose you want to reset an input field to its default value every time the user clicks a "Reset" button. The way to execute a JavaScript expression when the user clicks a button is using the v-on:click directive as shown below.

const app = new Vue({
  data: () => ({ value: 'Hello, World' }),
  template: `
    <div id="rendered-content">
      <div><input v-model="value"></input></div>
      <button v-on:click="value = 'Hello, World'">
        Reset
      </button>
    </div>
  `
});

Everything after v-on: is the name of the event Vue will listen to. So v-on:click tells Vue to register a listener for the native 'click' event.

There's nothing special about the 'click' event. You can use v-on: to listen to any native event, like:

@ Shorthand

Vue has a convenient shorthand for v-on: the @ symbol. For example, @click is functionally equivalent to v-on:click. Using @ saves you a few keystrokes, but v-on is more readable for people who aren't familiar with Vue.

const app = new Vue({
  data: () => ({ value: 'Hello, World' }),
  // Uses `@click` instead of `v-on:click`
  template: `
    <div id="rendered-content">
      <div><input v-model="value"></input></div>
      <button @click="value = 'Hello, World'">
        Reset
      </button>
    </div>
  `
});

Many Vue codebases use @, so you should be familiar with it. However, you should prefer to use v-on for readability, unless you have a large codebase that you only expect experienced Vue developers to work with.

With Custom Components

Using $emit to send events to parent components is a core tenant of data flow in Vue. Even v-model uses v-on under the hood.

In Vue methods and expressions, you have access to a $emit() function that lets you emit an event up the component tree to the parent component. In the below example, the input-name component emits a 'update' event. The top-level app listens for 'update' events using v-on:update, and changes the name accordingly.

Vue.component('input-name', {
  data: () => ({ name: 'World' }),
  // When you click the "Update" button, Vue will emit an event `update`
  // to the parent, with the current state of 'name'.
  template: `
    <div>
      <input type="text" v-model="name">
      <button v-on:click="$emit('update', name)">
        Update
      </button>
    </div>
  `
});

const app = new Vue({
  data: () => ({ name: 'World' }),
  // To listen to the 'update' event, you create the `input-name`
  // component with a `v-on:update` attribute. `$event` contains
  // the value of the 2nd parameter to `$emit()`.
  template: `
    <div>
      <div>
        <input-name v-on:update="setName($event)"></input-name>
      </div>
      <h1>Hello, {{name}}</h1>
    </div>
  `,
  methods: {
    // Define a method that Vue will call to handle the 'update' event.
    setName: function(v) {
      this.name = v;
    }
  }
});
app.$mount('#content');

Vue School has some of our favorite Vue video courses. Their Vue.js Master Class walks you through building a real world application, and does a great job of teaching you how to integrate Vue with Firebase. Check it out!


Did you find this tutorial useful? Say thanks by starring our repo on GitHub!

More Vue Tutorials