Javascript chuẩn: Sử dụng data attribute

Điểm bài viết
[Tổng cộng: 0 Trung bình: 0]

Share vì hữu ích

Trong lập trình Javascript, việc triển khai mô hình module độc lập với các tính năng trở thành một phần không thể thiếu ngày nay. Hãy cùng xem cách Code Tốt chia sẻ việc xây dựng trên mối quan hệ thuộc tính data attribute trên markup như thế nào nhé.

Functional Programming trong Javascript

Functional programming (Lập trình theo chức năng) ngày càng trở thành chủ đề nóng trong cộng đồng Javascript. Chỉ vài năm trước đây, mới chỉ có vài lập trình viên biết nó là gì, nhưng hầu như các ứng dụng mà chúng ta có thể quan sát trong vòng 3 năm trở lại đây đều tận dụng rất mạnh lợi thế của ý tưởng lập trình theo chức năng.

Module hoá trong Javascript

Module trong lập trình web được hiểu là một khu vực trên website thực hiện những chức năng riêng biệt và logic của riêng nó (đọc thêm về T3 Framework đã có nói về điều này). Trong cùng một trang có thể chứa nhiều module, và cũng có thể lặp lại một module nhiều lần. Bởi vậy, việc đặt ra giới hạn của module chỉ làm việc với các thành phần tương tác bên trong nó là rất quan trọng, giúp code sạch và gọn hơn nhiều.

Thêm nữa, các module được đóng gói và có tính khu biệt cao sẽ biết dừng lại ở đâu khi thực thi, và nó hoàn tất vòng đời của nó mà thôi.

Cách thức tiến hành module hoá

Mỗi module cần có một element trong trang đại diện cho nó. Để xác định đối tượng đại diện, ta nên sử dụng data attribute được hỗ trợ trong HTML5 như các ví dụ sau:

<div class="hero" data-module="hero">
  <!-- Markup của module ở bên trong -->
</div>

Tên module trong markup

Lưu ý rằng với thuộc tính data-module như ta vừa nêu trên, không bắt buộc phải có class hoặc tên trùng khớp. Chẳng hạn, với một chức năng tôi viết anonymous (tức xác định các chủ thể bằng các class độc lập — phần này sẽ nói ở bước tiếp theo), ta có thể gọi như sau:

<div class="hero" data-module="next-section">
  <a href="#" class="hero__button"></a>
</div>

Như vậy, nhiệm vụ của module tên là next-section sẽ không còn cần đặt tên là hero.js như ta nghĩ nữa.

Gán các selector hợp lý bằng prefix js-xxx

Sau khi ta xác định được đối tượng đóng vai trò wrap chính của module, ta cần nghĩ tới việc các đối tượng bên trong nó cũng cần anonymous và dễ dàng gọi tới bằng các selector riêng.

Chẳng hạn, trong module next-section.js, tôi sẽ chỉ làm thao tác như sau:

import smoothScroll from 'modules/smooth-scroll'
import { closest } from 'modules/utils/utils'

export default function nextScroll (el) {
  const trigger = el.querySelector('.js-next-section')
  const section = closest(el, '.section')
  if (trigger) {
    trigger.addEventListener('click', () => smoothScroll(section.nextElementSibling))
  }
}

Như vậy, đối tượng el ở đây chính là el.querySelector('.js-next-section') và khi click vào nó thì thực thi một thao tác là tìm parent của section, sau đó scroll xuống.

Tất nhiên, để nó hoạt động được thì trong file main.js (file JS gốc), bạn cần gọi tới document.querySelectorAll('[data-module]') và thực thi init() nó để khi load page thì mỗi module tự nó thực hiện các function cần thiết. Phần này hơi chi tiết, ta sẽ đề cập ở một bài viết khác.

Triển khai data attribute options cho module

Nhiều module cần xác định thêm các thành phần phụ để thực hiện, ví dụ như cũng là chức năng scroll xuống, nhưng tôi muốn xác định cụ thể sẽ scroll xuống anchor nào thì sao?

Như vậy, ta sẽ nghĩ tới việc tiếp tục xây dựng các thuộc tính data-attribute khác để phục vụ cho việc dễ dàng tái sử dụng module này trên các markup khác.

Hãy cùng xem 1 ví dụ cụ thể như sau:

Trong markup:

<div class="hero" data-module="scroll">
  <a href="#" class="hero__button js-scroll" data-target="#three-up">Read more</a>
  <a href="#" class="hero__button js-scroll" data-target="#intro">See How It Works</a>
</div>

Trong code Javascript:

import smoothScroll from 'modules/smooth-scroll'

export default function pageScroll (el) {
 const triggers = el.querySelectorAll('.js-next-section')
 const 
 if (triggers) {
   triggers.map( (trigger) => {
     const target = select(trigger.getAttribute('data-target'))
     if (target) {
       trigger.addEventListener('click', () => {
         smoothScroll(target)
       })
     }
   })
 }
}

Với cách viết xác định thuộc tính data-attribute như vậy, bạn sẽ dễ dùng hơn căn cứ phụ thuộc vào href chẳng hạn, vì có thể đối tượng click không phải a mà là button thì sao?

Tham khảo thêm

Video – Revealing Module Pattern Javascript Tutorial
Javascript Module for beginner

Kết luận

Với các gợi ý của Code Tốt về việc quy hoạch và xây dựng module hoá, hi vọng các bạn có thể nghiên cứu và đưa ra những cách làm cụ thể giúp tăng hiệu năng cho website của mình.

Share vì hữu ích

About Khôi 'Pro' Nguyễn

Technical Lead tại Solis Lab. Quản lý ngôn ngữ tại vi.wordpress.org.

View all posts by Khôi 'Pro' Nguyễn →

Trả lời