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');

More Vue Tutorials