Car News

Hướng dẫn noUiSlider cho thị trường Việt Nam: Cài đặt, cấu hình, ví dụ thực tế và tối ưu SEO

noUiSlider là thư viện thanh trượt (range slider) nhỏ gọn, mượt mà, linh hoạt, hoạt động tốt với jQuery/Zepto. Bài viết này tổng hợp cách dùng từ cơ bản đến nâng cao, bao gồm cấu hình range, step, connect, snap, định dạng số, trục dọc/RTL, pips (mốc hiển thị), sự kiện, liên kết với input và mẹo tối ưu hiệu năng.

Lưu ý: Cú pháp ví dụ dưới đây tương thích với nhánh API jQuery của noUiSlider (phiên bản cũ sử dụng $(el).noUiSlider({…}) và .val()).

1) Cài đặt nhanh

  • Thêm jQuery (hoặc Zepto)
  • Thêm file CSS/JS noUiSlider tương ứng phiên bản bạn dùng
  • Tạo một phần tử chứa slider, ví dụ:

Ví dụ HTML cơ bản:

<link rel="stylesheet" href="nouislider.css">
<script src="jquery.min.js"></script>
<script src="jquery.nouislider.min.js"></script>

<div id="price"></div>

2) Khởi tạo slider cơ bản

Khởi tạo thanh trượt một giá trị:

$('#price').noUiSlider({
  start: [50],
  range: { min: 0, max: 100 },
  step: 1
});

Khởi tạo range slider hai tay nắm:

$('#price').noUiSlider({
  start: [20, 80],
  range: { min: 0, max: 100 },
  step: 1,
  connect: true // tô đậm vùng giữa hai tay nắm
});

Mẹo SEO nội dung: khi mô tả UI filter theo giá, dùng từ khóa “thanh trượt giá”, “slider lọc sản phẩm”, “range slider JavaScript” để phù hợp ngữ cảnh thương mại điện tử.

3) Lấy và gán giá trị với .val()

noUiSlider cũ ghi đè jQuery .val() trên phần tử slider:

// Lấy giá trị hiện tại (trả về số hoặc mảng số)
var current = $('#price').val();

// Gán giá trị mới
$('#price').val([30, 70]);
  • Slider 1 tay: .val() trả về số
  • Slider 2 tay: .val() trả về mảng [lower, upper]

4) Tùy chọn quan trọng và cách dùng đúng

  • range: định nghĩa biên min/max (bắt buộc)
  • start: giá trị khởi tạo (một số hoặc mảng)
  • step: bước nhảy (số)
  • connect:
    • false: không tô vùng
    • ‘lower’ (1 tay), ‘upper’ (1 tay)
    • true (2 tay): tô vùng giữa
  • orientation: ‘horizontal’ hoặc ‘vertical’
  • direction: ‘ltr’ hoặc ‘rtl’ (hữu ích cho ngôn ngữ RTL/giá trị đảo)
  • snap: true để tay nắm “hít” vào các bước/điểm
  • animate: true/false (hiệu ứng chuyển động)
  • margin: khoảng cách tối thiểu giữa hai tay nắm (linear range)
  • limit: khoảng cách tối đa giữa hai tay nắm (linear range)
  • behaviour: ‘tap’ | ‘drag’ | ‘fixed’ | ‘snap’ (có thể kết hợp, ví dụ: ‘tap drag’)

Ví dụ connect và định hướng:

$('#price').noUiSlider({
  start: [25, 75],
  range: { min: 0, max: 100 },
  connect: true,          // tô giữa
  orientation: 'horizontal',
  direction: 'ltr',
  behaviour: 'tap drag'
});

Vertical + RTL:

$('#height').noUiSlider({
  start: [150, 190],
  range: { min: 100, max: 220 },
  connect: true,
  orientation: 'vertical',
  direction: 'rtl'
});

5) Định dạng số (format) thân thiện SEO

Bạn có thể truyền đối tượng format với 2 hàm to/from để hiển thị số đẹp hơn (phân cách hàng nghìn, đơn vị, làm tròn).

Ví dụ hiển thị “đ” và phân tách hàng nghìn:

var formatVND = {
  to: function (value) {
    return Math.round(value).toString().replace(/B(?=(d{3})+(?!d))/g, '.') + ' đ';
  },
  from: function (value) {
    return Number(value.replace(/[^d]/g, ''));
  }
};

$('#price').noUiSlider({
  start: [1000000, 5000000],
  range: { min: 0, max: 10000000 },
  step: 50000,
  connect: true,
  format: formatVND
});

Gợi ý nội dung: sử dụng cụm từ “định dạng tiền tệ VND”, “phân tách hàng nghìn”, “giá sản phẩm” để tăng tính liên quan.

6) Sử dụng pips (mốc hiển thị) làm thước đo

Pips giúp hiển thị mốc trên thanh trượt để người dùng ước lượng nhanh.

$('#price').noUiSlider({
  start: [20, 80],
  range: { min: 0, max: 100 },
  connect: true
});

// Thêm pips
$('#price').noUiSlider_pips({
  mode: 'positions',    // 'range' | 'steps' | 'positions' | 'count'
  values: [0, 25, 50, 75, 100],
  density: 2,           // mật độ tick nhỏ
  stepped: true,        // bám step
  format: { to: function(v) { return v + '%'; } }
});

Các chế độ pips:

  • range: tự suy theo range
  • steps: hiển thị trên mỗi step
  • positions: theo % vị trí
  • count: số lượng mốc đều nhau

7) Giới hạn khoảng cách: margin và limit

  • margin: khoảng cách tối thiểu giữa 2 tay nắm
  • limit: khoảng cách tối đa giữa 2 tay nắm
$('#range').noUiSlider({
  start: [30, 60],
  range: { min: 0, max: 100 },
  connect: true,
  margin: 10, // không cho < 10%
  limit: 50   // không cho > 50%
});

Áp dụng tốt cho bộ lọc giá để ngăn người dùng chọn vùng quá hẹp hoặc quá rộng.

8) Sự kiện và tương tác

Các sự kiện thường dùng:

  • slide: khi đang kéo
  • set: khi thả tay hoặc set giá trị
  • change: thay đổi hoàn tất
  • update: cập nhật UI (tùy phiên bản)

Ví dụ:

var $slider = $('#price').noUiSlider({
  start: [20, 80],
  range: { min: 0, max: 100 },
  connect: true
});

$slider.on('slide', function (e, lower, upper) {
  // lower/upper có thể là số hoặc chuỗi đã format tùy theo 'format'
  // Cập nhật UI, ví dụ:
  $('#min').text(lower);
  $('#max').text(upper);
});

$slider.on('set change', function () {
  // Gửi analytics hoặc trigger lọc
});

Lưu ý: Tên tham số callback có thể khác nhau giữa các phiên bản; hãy kiểm thử thực tế.

9) Liên kết slider với input

Cách phổ biến là đồng bộ giá trị slider vào input để người dùng có thể nhập trực tiếp.

Cách 1: Đọc/ghi bằng .val() của slider và input:

var $slider = $('#price').noUiSlider({
  start: [100, 500],
  range: { min: 0, max: 1000 },
  connect: true
});

var $min = $('#minInput');
var $max = $('#maxInput');

// Đồng bộ từ slider -> input
$slider.on('set update', function () {
  var v = $slider.val();       // [min, max]
  $min.val(v[0]);
  $max.val(v[1]);
});

// Đồng bộ từ input -> slider
$min.on('change', function () {
  $slider.val([Number($min.val()), null]); // giữ nguyên max
});
$max.on('change', function () {
  $slider.val([null, Number($max.val())]); // giữ nguyên min
});

Mẹo:

  • Xử lý hợp lệ số liệu (NaN) trước khi gán
  • Với format tiền tệ, cần “from” để parse đúng

10) Snap và bước động

Bật snap để tay nắm “hít” vào điểm:

$('#snap').noUiSlider({
  start: [0],
  range: { min: 0, max: 100 },
  snap: true,
  step: 10
});

Với dải bước không đều (advanced), bạn có thể cấu hình range dạng nhiều mốc:

$('#multiStep').noUiSlider({
  start: [20],
  range: {
    'min': [0],
    '25%': [25, 5],   // bước 5 giữa 25% và 50%
    '50%': [50, 10],  // bước 10 giữa 50% và 75%
    '75%': [75, 5],
    'max': [100]
  },
  snap: true
});

11) Lấy thông tin cấu hình và bước hiện tại

  • Lấy options gốc:

    var options = $('#price').noUiSlider('options');
  • Lấy bước hiện tại (current step) ở vị trí tay nắm:

    var stepInfo = $('#price').noUiSlider('step'); 
    // Tùy phiên bản, trả về step áp dụng hoặc mảng step của từng tay nắm

12) Hiệu năng và khả dụng

  • Hiệu năng:

    • Tránh lắng nghe sự kiện quá dày (debounce/throttle khi filter)
    • Hạn chế sửa DOM liên tục trong callback; gộp cập nhật
    • Bật animate khi cần trải nghiệm mượt; tắt khi cần hiệu suất khắt khe
  • Khả dụng:

    • Tương phản màu connect/handle đủ rõ
    • Kích thước handle phù hợp cảm ứng
    • Cân nhắc hiển thị pips/label để định hướng người dùng
  • SEO nội dung (gián tiếp):

    • Mô tả rõ ràng mục đích thanh trượt trong nội dung xung quanh
    • Gắn nhãn gần slider: “Giá tối thiểu”, “Giá tối đa”, “Khoảng chiều cao” giúp công cụ hiểu ngữ cảnh

13) Khắc phục lỗi thường gặp

  • Không khởi tạo được: kiểm tra đã nạp đúng thứ tự jQuery → noUiSlider chưa
  • .val() trả về chuỗi format: hãy cấu hình format.from để chuyển về số khi cần tính toán
  • margin/limit không hoạt động: chỉ hỗ trợ linear range; không áp dụng cho range phân đoạn phức tạp
  • Sự kiện không bắn: xác nhận tên sự kiện phù hợp phiên bản; console.log trong callback để kiểm tra
  • RTL/vertical lệch hướng: xác nhận direction và orientation đồng bộ với CSS

14) Mẫu tổng hợp: Lọc giá VND có pips, animate và định dạng

<div class="filter">
  <label>Khoảng giá</label>
  <div id="priceRange"></div>
  <div class="inputs">
    <input id="minVnd" type="text" inputmode="numeric">
    <input id="maxVnd" type="text" inputmode="numeric">
  </div>
</div>
var formatVND = {
  to: function (value) {
    return Math.round(value).toString().replace(/B(?=(d{3})+(?!d))/g, '.') + ' đ';
  },
  from: function (value) {
    return Number((value || '').toString().replace(/[^d]/g, '')) || 0;
  }
};

var $slider = $('#priceRange').noUiSlider({
  start: [1500000, 7000000],
  range: { min: 0, max: 10000000 },
  step: 50000,
  connect: true,
  animate: true,
  format: formatVND,
  behaviour: 'tap drag'
});

$('#priceRange').noUiSlider_pips({
  mode: 'count',
  values: 5,
  density: 2,
  stepped: true,
  format: { to: function(v){ return (v/100*10).toFixed(1) + 'M'; } } // ví dụ nhãn 0–10M
});

// Liên kết input
var $min = $('#minVnd');
var $max = $('#maxVnd');

$slider.on('update', function () {
  var v = $slider.val();
  $min.val(v[0]);
  $max.val(v[1]);
});

$min.on('change', function () {
  var min = formatVND.from($min.val());
  var cur = $slider.val();
  $slider.val([min, cur[1]]);
});

$max.on('change', function () {
  var max = formatVND.from($max.val());
  var cur = $slider.val();
  $slider.val([cur[0], max]);
});

15) Kết luận

  • noUiSlider cung cấp range slider gọn nhẹ, mượt, dễ tích hợp với jQuery
  • Dải tùy chọn phong phú: connect, step, snap, margin/limit, vertical/RTL, định dạng số
  • Pips hỗ trợ thước đo trực quan; .val() giúp get/set dễ dàng
  • Áp dụng tốt cho bộ lọc giá, khoảng thời gian, kích thước, điểm số, cấu hình sản phẩm

Khi triển khai thực tế, hãy kiểm thử trên các thiết bị cảm ứng, tối ưu trải nghiệm kéo thả và đảm bảo dữ liệu đầu ra chính xác để hỗ trợ cả SEO nội dung và chuyển đổi người dùng.

Related posts

Xe đạp điện Honda: Bảng giá, đánh giá chi tiết A6 Plus, M8, A8 Plus, M7, M6 và kinh nghiệm mua

admin

Honda Winner X: đánh giá chi tiết thiết kế, vận hành, chi phí và gợi ý chọn phiên bản

admin

Phủ Ceramic Cho Ô Tô: Hướng Dẫn Toàn Diện, Bảng Giá, Quy Trình Và Bảo Dưỡng 2025

admin

Leave a Comment