0
0
Lập trình
Admin Team
Admin Teamtechmely

5 Chiến Lược Dropdown Phụ Thuộc Với HTMX Dễ Dàng

Đăng vào 7 tháng trước

• 11 phút đọc

Chủ đề:

KungFuTech

Giới thiệu

Chào mọi người! 👋

Gần đây, tôi đã bắt đầu hành trình trở thành một "nhà phát triển fullstack tối giản" — cố gắng xây dựng các ứng dụng web vững chắc với những công cụ cơ bản thay vì chìm đắm trong sự phức tạp của các framework. Bạn biết đấy, một ngày bạn thêm React cho một biểu mẫu đơn giản, và ngay lập tức bạn có 47 phụ thuộc và một quá trình xây dựng lâu hơn thời gian phát triển thực tế của bạn.

Đó là khi tôi phát hiện ra HTMX, và thành thật mà nói, nó đã thay đổi cuộc chơi cho việc xây dựng các giao diện tương tác mà không cần đến sự lộn xộn của JavaScript. Nhưng hôm nay, tôi muốn chia sẻ một điều cụ thể mà tôi đã mất quá nhiều thời gian để tìm hiểu: dropdown phụ thuộc.

Bạn biết quy trình rồi — người dùng chọn một quốc gia, dropdown thành phố sẽ được cập nhật. Người dùng chọn một danh mục, sản phẩm sẽ được lọc tương ứng. Nghe có vẻ đơn giản, đúng không? Thực ra, tôi đã thử khoảng 5 cách tiếp cận khác nhau trước khi tìm ra các mô hình thực sự hoạt động tốt trong sản xuất.

Vấn Đề Khởi Đầu

Tôi đang xây dựng một hệ thống lọc thương mại điện tử. Không có gì phức tạp — chỉ là dropdown Quốc Gia → Tiểu Bang → Thành Phố cho việc giao hàng. Phản xạ đầu tiên của tôi là sử dụng React hoặc Vue, nhưng rồi tôi nhớ đến mục tiêu tối giản của mình. Thực sự thì việc này có khó không với HTMX?

Cảnh báo: Tôi đã làm cho mọi thứ trở nên khó khăn hơn mức cần thiết.

Sau vô số tab Stack Overflow và vài lỗi sản xuất đáng xấu hổ (RIP sự tập trung của người dùng khi dropdown được cập nhật), cuối cùng tôi đã tìm ra cách. Dưới đây là 5 chiến lược mà tôi đã khám phá, xếp hạng từ "nhất định sử dụng" đến "cảm ơn bạn đã không mắc sai lầm của tôi."

Chiến Lược 1: Người Nghe Ẩn (Sự Lựa Chọn Yêu Thích Của Tôi)

Đây trở thành chiến lược yêu thích của tôi sau khi học được nó theo cách khó khăn. Ý tưởng rất đơn giản: sử dụng các phần tử ẩn lắng nghe sự thay đổi từ dropdown chính của bạn.

html Copy
<!-- Dropdown chính của bạn -->
<select name="country" id="country">
    <option value="usa">Hoa Kỳ</option>
    <option value="canada">Canada</option>
</select>

<!-- Người nghe ẩn (đây là phần quan trọng) -->
<div hx-trigger="change from:#country"
     hx-get="/api/cities"
     hx-target="#cities-container"
     hx-include="[name='country']"
     style="display: none;"></div>

<!-- Nơi thành phố sẽ xuất hiện -->
<div id="cities-container">
    <select name="city" disabled>
        <option>Chọn quốc gia trước</option>
    </select>
</div>

Và backend Node.js thì rất đơn giản:

javascript Copy
app.post('/api/cities', (req, res) => {
    const { country } = req.body;
    const cities = getCitiesForCountry(country);

    const options = cities.map(city => 
        `<option value="${city.code}">${city.name}</option>`
    ).join('');

    res.send(`
        <select name="city">
            <option value="">Chọn thành phố...</option>
            ${options}
        </select>
    `);
});

Tại sao tôi thích cách tiếp cận này:

  • Phân tách rõ ràng: dropdown thực hiện chức năng của nó, người nghe thực hiện lắng nghe.
  • Sự tập trung của người dùng luôn ở đúng nơi cần thiết.
  • Dễ dàng gỡ lỗi khi có vấn đề xảy ra (và chúng sẽ xảy ra).
  • Mở rộng dễ dàng khi bạn cần từ 5 dropdown trở lên.

Nhược điểm duy nhất: Nhiều yêu cầu HTTP. Nhưng thành thật mà nói? Trừ khi bạn đang xây dựng Amazon tiếp theo, điều này sẽ không phải là nút thắt cổ chai của bạn.

Chiến Lược 2: Nhiều Đích (Tốt Cho Trường Hợp Đơn Giản)

Khi tôi chỉ cần một sự phụ thuộc cơ bản giữa Quốc Gia → Thành Phố, đôi khi tôi sử dụng cách tiếp cận đơn giản:

html Copy
<select name="country"
        hx-get="/api/cities"
        hx-trigger="change"
        hx-target="#cities-container"
        hx-include="[name='country']">
    <option value="usa">Hoa Kỳ</option>
</select>

<div id="cities-container">
    <select name="city">...</select>
</div>

Hoàn hảo cho: Biểu mẫu liên hệ, nhập địa chỉ đơn giản, bất kỳ thứ gì có 2-3 dropdown tối đa.

Tránh sử dụng khi: Bạn có các phụ thuộc phức tạp hoặc hơn 3 cấp độ liên kết.

Chiến Lược 3: Hoán Đổi OOB (Khi Hiệu Suất Quan Trọng)

Cách này mất một thời gian để tôi hiểu, nhưng nó thật tuyệt cho các ứng dụng có lưu lượng truy cập cao. Một yêu cầu cập nhật nhiều dropdown đồng thời sử dụng "hoán đổi ngoài băng" của HTMX.

html Copy
<select name="country"
        hx-get="/api/update-all"
        hx-trigger="change"
        hx-target="this"
        hx-include="[name='country']">
</select>

<div id="cities-container">
    <select name="city">...</select>
</div>

<div id="products-container">
    <select name="product">...</select>
</div>

Backend kỳ diệu:

javascript Copy
app.post('/api/update-all', (req, res) => {
    const { country } = req.body;

    // Phản hồi chính cập nhật dropdown quốc gia
    let response = `<option value="${country}" selected>${getCountryName(country)}</option>`;

    // Những cái này cập nhật các dropdown khác "ngoài băng"
    response += `
    <div id="cities-container" hx-swap-oob="true">
        <select name="city">
            ${renderCityOptions(country)}
        </select>
    </div>

    <div id="products-container" hx-swap-oob="true">
        <select name="product">
            ${renderProductOptions(country)}
        </select>
    </div>`;

    res.send(response);
});

Khi nào sử dụng điều này: Các trang web có lưu lượng truy cập cao, các biểu mẫu phức tạp mà mọi thứ phụ thuộc vào nhau, khi bạn muốn giảm thiểu vòng lặp máy chủ.

Cảnh báo về độ khó: Hoán đổi OOB có thể khó gỡ lỗi. Bắt đầu với người nghe ẩn, sau đó phát triển lên khi bạn cần tăng hiệu suất.

Chiến Lược 4: Chuỗi Sự Kiện (Đối Với Logic Phức Tạp)

Đôi khi bạn cần cập nhật có điều kiện hoặc logic kinh doanh phức tạp. Đó là khi tôi sử dụng JavaScript:

html Copy
<select name="country" id="country"
        hx-get="/api/countries"
        hx-trigger="change"
        hx-target="this">
</select>

<script>
htmx.on('htmx:afterSwap', function(evt) {
    if (evt.target.id === 'country') {
        const country = evt.target.value;

        // Cập nhật thành phố
        htmx.ajax('GET', '/api/cities', {
            source: '#country',
            target: '#cities-container'
        });

        // Có thể cập nhật sản phẩm, nhưng chỉ cho một số quốc gia nhất định
        if (['usa', 'canada'].includes(country)) {
            htmx.ajax('GET', '/api/products', {
                source: '#country',
                target: '#products-container'
            });
        }
    }
});
</script>

Hoàn hảo cho: Các wizard đa bước, biểu mẫu với các trường có điều kiện, khi logic kinh doanh trở nên phức tạp.

Sử dụng một cách tiết kiệm: Nhiều JavaScript có nghĩa là phức tạp hơn. Tôi chỉ sử dụng điều này khi các chiến lược khác không thể đáp ứng yêu cầu của tôi.

Chiến Lược 5: Thay Thế Biểu Mẫu (Xin Đừng)

Tôi đưa điều này vào vì tôi đã mắc phải sai lầm này từ sớm, và tôi muốn giúp bạn tránh đau khổ:

html Copy
<!-- ĐỪNG LÀM ĐIỀU NÀY -->
<form id="myform">
    <select name="country"
            hx-get="/update-form"
            hx-trigger="change"
            hx-target="#myform"
            hx-swap="outerHTML">
    </select>
</form>

Tại sao điều này tệ:

  • Người dùng mất tập trung mỗi lần (rất khó chịu).
  • Trạng thái biểu mẫu sẽ bị xóa.
  • Kinh nghiệm truy cập tồi tệ.
  • Người dùng di động sẽ ghét bạn.

Tôi đã học bài học này khi một người dùng phàn nàn rằng họ không thể điền vào biểu mẫu địa chỉ của chúng tôi trên di động. Hóa ra, mỗi lần họ chọn một quốc gia, bàn phím sẽ biến mất vì mất tập trung. Oops.

Cây Quyết Định (Giúp Bạn Tiết Kiệm Thời Gian)

Dưới đây là cách tôi quyết định chiến lược nào để sử dụng hiện tại:

  • Xây dựng một cái gì đó mới? → Bắt đầu với Người Nghe Ẩn.
  • Biểu mẫu 2-dropdown đơn giản? → Nhiều Đích là đủ.
  • Ứng dụng có lưu lượng truy cập cao? → Hoán Đổi OOB cho hiệu suất.
  • Logic điều kiện phức tạp? → Chuỗi Sự Kiện (nhưng chuẩn bị cho các phiên gỡ lỗi).
  • Thay thế biểu mẫu? → Chỉ cần không làm vậy. Thật sự đấy.

Ví Dụ Thực Tế Từ Các Dự Án Của Tôi

  • Bộ lọc sản phẩm thương mại điện tử: Người Nghe Ẩn
    • Nhiều bộ lọc độc lập, phân tách mạch lạc.
  • Biểu mẫu địa chỉ: Hoán Đổi OOB
    • Hiệu suất quan trọng, cập nhật nguyên tử.
  • Biểu mẫu liên hệ với quốc gia/tiểu bang: Nhiều Đích
    • Chỉ có 2 dropdown, giữ cho đơn giản.
  • Wizard onboarding đa bước: Chuỗi Sự Kiện
    • Các luồng điều kiện phức tạp, các con đường khác nhau cho các loại người dùng khác nhau.

Các Vấn Đề Bảo Mật Backend (Đừng Bỏ Qua)

Vì chúng ta đang xử lý dữ liệu người dùng, đây là những gì tôi đã học về việc giữ cho mọi thứ an toàn:

javascript Copy
const { body, validationResult } = require('express-validator');

// Xác thực mọi thứ
const validateCountry = [
    body('country')
        .isAlpha()
        .isLength({ min: 2, max: 3 })
        .withMessage('Mã quốc gia không hợp lệ')
];

app.post('/api/cities', validateCountry, (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
        return res.status(400).send(`
            <div class="error">Yêu cầu không hợp lệ</div>
        `);
    }

    // An toàn để xử lý...
});

// Luôn luôn thoát HTML
function escapeHtml(unsafe) {
    return unsafe
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;");
}

Mẹo Hiệu Suất Mà Tôi Muốn Biết Sớm Hơn

Sử dụng độ trễ cho các đầu vào tìm kiếm:

html Copy
hx-trigger="input delay:300ms"

Lưu trữ các dữ liệu rõ ràng:

Dữ liệu quốc gia/tiểu bang không thay đổi thường xuyên. Lưu trữ nó.

Giữ cho phản hồi nhỏ:

Chỉ trả về HTML cần thiết, không phải các đoạn mã lớn.

Cân nhắc lưu trữ CDN:

Các tùy chọn dropdown tĩnh (quốc gia, tiểu bang) rất phù hợp để lưu trữ CDN.

Kết Luận

HTMX thực sự đã thay đổi cách tôi suy nghĩ về việc xây dựng các ứng dụng web tương tác. Không có bước xây dựng, không có kích thước gói khổng lồ, không phải đấu tranh với việc quản lý trạng thái — chỉ cần HTML nói chuyện với máy chủ của bạn khi cần thiết.

Các mẫu dropdown phụ thuộc mà tôi đã chia sẻ ở đây hoạt động tốt trong sản xuất. Tôi đã sử dụng chúng trong nhiều dự án khác nhau, từ các biểu mẫu liên hệ đơn giản đến các bộ lọc thương mại điện tử phức tạp. Bắt đầu với người nghe ẩn, và bạn sẽ tìm thấy chúng giải quyết 80% các trường hợp sử dụng của bạn.

Điều tốt nhất? Khi bạn cần chuyển giao mã cho một nhà phát triển khác, họ có thể đọc HTML và ngay lập tức hiểu những gì đang diễn ra. Không cần tài liệu về các phương pháp vòng đời thành phần hay mẫu quản lý trạng thái. Chỉ cần: "Khi cái này thay đổi, cập nhật cái kia."

Đó là kiểu đơn giản mà tôi đang tìm kiếm trong hành trình fullstack tối giản của mình.


Bạn đã thử HTMX cho các dropdown phụ thuộc chưa? Tôi rất muốn nghe về trải nghiệm của bạn — đặc biệt nếu bạn đã tìm ra các mẫu mà tôi chưa xem xét. Để lại một bình luận bên dưới hoặc liên hệ với tôi trên Twitter!

Bạn muốn thêm mẹo HTMX? Tôi đang lên kế hoạch cho một chuỗi bài viết về việc xây dựng các ứng dụng full-stack với ít phụ thuộc. Theo dõi tôi để cập nhật, và cho tôi biết những chủ đề bạn muốn tôi đề cập tiếp theo.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào