Với nhiều người đã sử dụng Javascript (ES5) hay jQuery, việc biến JS trở thành 1 mớ bòng bong dường như là chuyện thường như cơm bữa. Code Tốt xin chia sẻ cách xây dựng mindset functional programming (ở mức cơ bản) để giải quyết bài toán logic khi xử lý vấn đề.
Functional Programming trong Javascript
Với ngôn ngữ như JS, xử lý ở Functional Programming có vẻ là 1 phương án lý tưởng. Functional Programming cũng có 2 xu hướng: xử lý các function và trả về 1 object, hoặc xử lý các function và không trả về kết quả gì cả (tức là thực thi mà thôi).
Ở mức cơ bản được nhắc đến trong bài viết này, bạn có thể chỉ cần nắm được việc xử lý và sử dụng các function gọn gàng đã làm một thành công. Bước nâng cao hơn mới là xây dựng đầu vào và đầu ra cho mỗi function.
Bài toán xây dựng một Accordion (dạng FAQ list)
Giả sử Code Tốt và các bạn cần xây dựng 1 list FAQ item chứa các hidden content, khi click vào item thì hiện ra.
Bài toán cần xử lý các tình huống sau:
- Khi chưa có item nào active, thì active item vừa được click.
- Khi có item nào đó khác đang active, thì disable item này trước khi acive item vừa được click.
- Trong cùng 1 thời điểm chỉ có 1 item active
[sociallocker]
Với lối tư duy cơ bản, hẳn bạn sẽ bind click vào item và lục lọi tìm các item children và item siblings đúng không? Hãy suy nghĩ lại chút nào. Giờ ta sẽ định nghĩa các hành động thông qua mỗi function. Chẳng hạn như ta sẽ có 3 function dưới đây:
var activeClass = 'active'; // Đây là các items nằm trong .list var items = Array.prototype.slice.call( document.querySelectorAll('.js-item') ); // Đây là các toggle (thường là header của item) var toggles = Array.prototype.slice.call( document.querySelectorAll( '.js-toggle') ); function activeItem( item ) {} function deactiveItem( item ) {} function deactiveItems() {}
Function activeItem
và deactiveItem
sẽ cần đầu vào là item mà chúng ta click, trong khi function deactiveItems
sẽ lấy từ global variables $items
mà ta đã định nghĩa ở trên.
Rõ ràng, nhìn mô hình trên, bạn sẽ hiểu được logic đầu tiên (mà khi chưa click):
- Bất cứ item nào được truyền qua function
activeItem
haydeactiveItem
sẽ chỉ làm nhiệm vụ active/deactive item đó thôi. - Bất cứ khi nào gọi
deactiveItems
thì tất cả item sẽ đều bị deactive.
Kết hợp tiếp cùng yếu tố bind click vào item, ta sẽ có thêm logic khi click như sau:
toggles.forEach( function( toggle ) { toggle.addEventListener('click', function() { // Tìm item parent var item = this.parentNode; if( item.classList.contains( activeClass ) ) { deactiveItem( item ); } else { deactiveItems(); activeItem( item ); } }); } );
Bạn thấy vấn đề đã được định nghĩa logic rõ ràng hơn chưa? Code gọn gàng, có phân tách ra các bước xử lý độc lập hơn hẳn rồi đấy.
Bạn có thể tham khảo code mẫu tại đây.
[/sociallocker]
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.
Thanks so much ^^