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.
Giám đốc tại Công ty CP CODE TỐT. Quản lý ngôn ngữ bản địa tiếng Việt tại WordPress. Là tác giả chính tại codetot.net, Khôi muốn ghi lại một sốvấn đề kỹ thuật trong quá trình phát triển các dự án website với khách hàng.