For AI agents: the complete documentation index is available at https://nhanbe.id.vn/llms.txt, the full documentation bundle is available at https://nhanbe.id.vn/llms-full.txt, and this page is available as Markdown at https://nhanbe.id.vn/frontend/vue2.7/event-handling.md.

Listening to DOM events, inline handlers, and event modifiers in Vue 2.7.

Event Handling

Lắng nghe DOM event bằng v-on. Trong AEM, đây là cách xử lý tương tác trên UI Vue mount lên DOM mà HTL render: click button, submit form, gõ input, đóng/mở panel.

v-on và cú pháp rút gọn

v-on:event lắng nghe một DOM event. Rút gọn bằng @.

<button v-on:click="onClick">Click</button>

<!-- rút gọn, dùng phổ biến hơn -->
<button @click="onClick">Click</button>

Inline handler vs method handler

Logic ngắn viết thẳng (inline). Logic phức tạp tách thành method.

<!-- inline: biểu thức ngắn -->
<button @click="counter += 1">Add 1</button>

<!-- method: truyền tên method, không có ngoặc -->
<button @click="greet">Greet</button>

<!-- method có tham số: gọi kèm ngoặc -->
<button @click="say('hi')">Say hi</button>
methods: {
  greet(event) {
    // truyền tên method thì handler nhận native event làm tham số đầu
    console.log(this.name, event.target.tagName)
  },
  say(message) {
    console.log(message)
  }
}

Khi truyền tên method (không ngoặc), Vue tự truyền native DOM event vào tham số đầu tiên. Khi gọi có ngoặc, phải tự truyền event nếu cần.

Truy cập native event với $event

Cần cả tham số tùy chỉnh lẫn native event trong inline handler thì dùng biến đặc biệt $event.

<button @click="warn('Chưa submit được', $event)">Submit</button>
methods: {
  warn(message, event) {
    if (event) event.preventDefault()
    console.log(message)
  }
}

Event modifiers

Thay vì gọi event.preventDefault() / event.stopPropagation() trong method, dùng modifier để giữ method chỉ lo data logic.

ModifierTác dụng
.stopevent.stopPropagation()
.preventevent.preventDefault()
.selfChỉ chạy khi event.target là chính phần tử đó, không phải con
.captureThêm listener ở capture phase
.onceChỉ chạy tối đa 1 lần
.passiveBáo browser không gọi preventDefault, tối ưu scroll (mobile)
<!-- chặn reload trang khi submit form -->
<form @submit.prevent="onSubmit"></form>

<!-- chặn nổi bọt sự kiện -->
<a @click.stop="doThis"></a>

<!-- chain nhiều modifier -->
<a @click.stop.prevent="doThat"></a>

<!-- chỉ dùng modifier, không cần handler -->
<form @submit.prevent></form>

Thứ tự modifier quan trọng vì code sinh ra theo đúng thứ tự. @click.prevent.self chặn mọi click, còn @click.self.prevent chỉ chặn click trên chính phần tử.

Không dùng .passive chung với .prevent: .prevent sẽ bị bỏ qua.

Key modifiers

Lọc theo phím khi nghe keyboard event. Dùng tên phím từ KeyboardEvent.key chuyển sang kebab-case.

<!-- chỉ submit khi nhấn Enter -->
<input @keyup.enter="submit">

<!-- phím PageDown -->
<input @keyup.page-down="onPageDown">

System modifier keys

Chỉ chạy handler khi đang giữ phím hệ thống: .ctrl, .alt, .shift, .meta (meta là Windows key trên Windows, Command trên Mac).

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

<!-- Alt + C -->
<input @keyup.alt.67="clear">

.exact kiểm soát chính xác tổ hợp phím:

<!-- chạy kể cả khi giữ thêm Alt/Shift -->
<button @click.ctrl="onClick">A</button>

<!-- chỉ chạy khi đúng Ctrl, không phím nào khác -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- chỉ chạy khi không giữ phím hệ thống nào -->
<button @click.exact="onClick">A</button>

Mouse button modifier: .left, .right, .middle.

Tips cho AEM

Vue mount lên DOM HTL render sẵn, event handler hoạt động bình thường trên cây component đó.

<!-- HTL mount point -->
<div id="filter-bar" data-endpoint="${model.searchEndpoint}"></div>
new Vue({
  el: '#filter-bar',
  data() {
    return {
      endpoint: this.$el.dataset.endpoint,
      keyword: ''
    }
  },
  methods: {
    onSearch() {
      // gọi API tới endpoint cấu hình từ dialog
      console.log('search', this.keyword, this.endpoint)
    }
  }
})
<!-- template Vue -->
<form @submit.prevent="onSearch">
  <input v-model="keyword" @keyup.enter="onSearch">
  <button type="submit">Tìm</button>
</form>

Lưu ý: chỉ gắn event lên phần tử nằm trong cây Vue đã mount. Phần HTML do HTL render ngoài mount point không nhận được v-on, cần xử lý bằng JS thuần hoặc đưa vào trong component.