Loại bỏ tất cả các lớp bắt đầu bằng một chuỗi nhất định


99

Tôi có một div có id="a"thể có bất kỳ số lớp nào được gắn vào nó, từ một số nhóm. Mỗi nhóm có một tiền tố cụ thể. Trong javascript, tôi không biết lớp nào từ nhóm nằm trên div. Tôi muốn có thể xóa tất cả các lớp với một tiền tố đã cho và sau đó thêm một tiền tố mới. Nếu tôi muốn xóa tất cả các lớp bắt đầu bằng "bg", làm cách nào để thực hiện điều đó? Một cái gì đó như thế này, nhưng nó thực sự hoạt động:

$("#a").removeClass("bg*");

Câu trả lời:


59

Với jQuery, phần tử DOM thực tế ở chỉ số 0, điều này sẽ hoạt động

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.*?\b/g, '');

34
Cẩn thận với cái này. Ranh giới từ phân chia trên ký tự gạch ngang ('-') và dấu chấm và các tên khác, vì vậy các tên lớp như "bg.a", "bg-a", v.v. sẽ không bị xóa mà được thay thế bằng ".a", "-a", v.v. Vì vậy, nếu bạn có các tên lớp với các ký tự dấu câu, bạn có thể gặp rắc rối khi chỉ chạy một thay thế regex đơn giản. Dưới đây là một sợi SO về từ định nghĩa ranh giới
Jakub P.

6
Câu trả lời của Kabir Sarin dưới đây với split ('') và indexOf là IMO tốt hơn vì nó sẽ không làm cho các lớp "zombie" có đặc điểm đặc biệt đó bật lên.
Jakub P. Ngày

2
Phương pháp này vẫn có thể được sử dụng với một regex tốt hơn, chẳng hạn như phương pháp được tìm thấy ở đây: stackoverflow.com/a/2644364/1333402
ssmith

109

Sự phân tách regex trên ranh giới từ \bkhông phải là giải pháp tốt nhất cho điều này:

var prefix = "prefix";
var classes = el.className.split(" ").filter(function(c) {
    return c.lastIndexOf(prefix, 0) !== 0;
});
el.className = classes.join(" ").trim();

hoặc dưới dạng mixin jQuery:

$.fn.removeClassPrefix = function(prefix) {
    this.each(function(i, el) {
        var classes = el.className.split(" ").filter(function(c) {
            return c.lastIndexOf(prefix, 0) !== 0;
        });
        el.className = $.trim(classes.join(" "));
    });
    return this;
};

Cập nhật ES6 2018:

const prefix = "prefix";
const classes = el.className.split(" ").filter(c => !c.startsWith(prefix));
el.className = classes.join(" ").trim();

9
Đây là cách tiếp cận tốt hơn so với sử dụng RegExp với \ b (kiểm tra ranh giới từ) vì nó ngăn 'lớp zombie' xuất hiện. Nếu bạn có các lớp như "tiền tố-hậu tố", thì 'câu trả lời hay nhất' trong chuỗi này sẽ để lại lớp '-suffix' vì \ b sẽ tách ra trước ký tự '-'. Split-map-join bạn giải pháp công trình xung quanh mà :) Tôi tạo ra một jQuery nhỏ cắm xung quanh giải pháp của bạn, Kabir: ( gist.github.com/2881585 )
Jakub P.

3
+1 Tôi cũng đồng tình, mọi câu trả lời khác dường như chỉ là một regex đơn giản sẽ phá vỡ các ranh giới từ không phải dấu cách. Nếu có thời gian vào ngày mai, tôi sẽ cung cấp một bài kiểm tra đơn vị chứng minh điều này.
mầm

1
Tôi thích nó mặc dù đây thực sự không phải là mã hợp lệ, vì hàm ẩn danh trong filterphải trả về một boolean. Điều này sẽ hoạt động:var classes = $(e).attr("class").split(" "); $(classes).each(function(i, item) { classes[i] = item.indexOf("prefix") === -1 ? item : "prefix-new"); }); $(e).attr("class", classes.join(" "));
Tim.

Một công dụng giải pháp bản đồ có giá trị hơn:$e.attr('class', $.map($e.attr('class').split(' '), function (klass) { return klass.indexOf(prefix) != 0 ? klass : undefined; }).join(' '));
M Miller

2
Cách tiếp cận này hoạt động tốt nhất. Tôi đã sử dụng plugin của @ JakubP. Một gợi ý nếu tôi có thể: Nó làm gì, khi nó trả về các lớp, nó gây ra rất nhiều dung lượng. Ví dụ: class="blackRow blackText orangeFace blackHead"sẽ trở lại class=" orangeFace "nếu bạn chạy removeClassPrefix("black");. Tôi giải quyết điều này bằng cách cắt tỉa kết quả như sau: el.className = $.trim(classes.join(" "));.
Albert

29

Tôi đã viết một plugin jQuery đơn giản - alterClass , giúp loại bỏ lớp ký tự đại diện. Tùy chọn cũng sẽ thêm các lớp.

$( '#foo' ).alterClass( 'foo-* bar-*', 'foobar' ) 

Cảm ơn Pete! Chỉ cần sử dụng plugin của bạn và nó hoạt động tuyệt vời ... đã giúp tôi tiết kiệm thời gian!
jordan.baucke

11

Bạn không cần bất kỳ mã jQuery cụ thể nào để xử lý việc này. Chỉ cần sử dụng RegExp để thay thế chúng:

$("#a").className = $("#a").className.replace(/\bbg.*?\b/g, '');

Bạn có thể sửa đổi điều này để hỗ trợ bất kỳ tiền tố nào nhưng phương pháp nhanh hơn ở trên vì RegExp sẽ chỉ được biên dịch một lần:

function removeClassByPrefix(el, prefix) {
    var regx = new RegExp('\\b' + prefix + '.*?\\b', 'g');
    el.className = el.className.replace(regx, '');
    return el;
}

9

Sử dụng chữ ký thứ 2 của $.fn.removeClass:

// Considering:
var $el = $('<div class="  foo-1 a b foo-2 c foo"/>');

function makeRemoveClassHandler(regex) {
  return function (index, classes) {
    return classes.split(/\s+/).filter(function (el) {return regex.test(el);}).join(' ');
  }
}

$el.removeClass(makeRemoveClassHandler(/^foo-/));
//> [<div class=​"a b c foo">​</div>​]

Kể từ jQuery v1.4, đây là cách tiếp cận tốt nhất.
Dinei

3

http://www.mail-archive.com/jquery-en@googlegroups.com/msg03998.html cho biết:

... và .removeClass () sẽ xóa tất cả các lớp ...

Nó phù hợp với tôi;)

hoan hô


Đây là một sự lựa chọn tốt hơn! Làm.
Afshin Mehrabani

12
Câu hỏi không hỏi làm thế nào để xóa tất cả các lớp mà nó hỏi làm thế nào để xóa tất cả các lớp bắt đầu bằng một chuỗi nhất định. Hai điều này rất, rất khác nhau.
Chris Harrison

3

Một cách tiếp cận tôi sẽ sử dụng bằng cách sử dụng các cấu trúc jQuery đơn giản và các hàm xử lý mảng, là khai báo một hàm lấy id của điều khiển và tiền tố của lớp và xóa tất cả các lớp. Mã được đính kèm:

function removeclasses(controlIndex,classPrefix){
    var classes = $("#"+controlIndex).attr("class").split(" ");
    $.each(classes,function(index) {
        if(classes[index].indexOf(classPrefix)==0) {
            $("#"+controlIndex).removeClass(classes[index]);
        }
    });
}

Bây giờ, chức năng này có thể được gọi từ bất kỳ đâu, khi nhấp vào nút hoặc từ mã:

removeclasses("a","bg");

2

Tôi đang tìm kiếm giải pháp cho chính xác cùng một vấn đề. Để loại bỏ tất cả các lớp bắt đầu bằng tiền tố "fontid_" Sau khi đọc bài viết này, tôi đã viết một plugin nhỏ mà tôi đang sử dụng bây giờ.

(function ($) {
        $.fn.removePrefixedClasses = function (prefix) {
            var classNames = $(this).attr('class').split(' '),
                className,
                newClassNames = [],
                i;
            //loop class names
            for(i = 0; i < classNames.length; i++) {
                className = classNames[i];
                // if prefix not found at the beggining of class name
                if(className.indexOf(prefix) !== 0) {
                    newClassNames.push(className);
                    continue;
                }
            }
            // write new list excluding filtered classNames
            $(this).attr('class', newClassNames.join(' '));
        };
    }(fQuery));

Sử dụng:

$('#elementId').removePrefixedClasses('prefix-of-classes_');

Đây là gì khác hơn là giải pháp của tôi với hơn 10x dòng và kém hiệu quả "bắt đầu chuỗi với" kiểm tra: - /
sarink

2

Đối với các trình duyệt hiện đại:

let element = $('#a')[0];
let cls = 'bg';

element.classList.remove.apply(element.classList, Array.from(element.classList).filter(v=>v.startsWith(cls)));

1

Tôi biết đó là một câu hỏi cũ, nhưng tôi đã tìm ra giải pháp mới và muốn biết liệu nó có nhược điểm không?

$('#a')[0].className = $('#a')[0].className
                              .replace(/(^|\s)bg.*?(\s|$)/g, ' ')
                              .replace(/\s\s+/g, ' ')
                              .replace(/(^\s|\s$)/g, '');

1

Trong một dòng ... Loại bỏ tất cả các lớp khớp với một biểu thức chính quy someRegExp

$('#my_element_id').removeClass( function() { return (this.className.match(/someRegExp/g) || []).join(' ').replace(prog.status.toLowerCase(),'');});

0

Câu trả lời của Prestaul rất hữu ích, nhưng nó không hoàn toàn phù hợp với tôi. Cách jQuery để chọn một đối tượng theo id không hoạt động. Tôi đã phải sử dụng

document.getElementById("a").className

thay vì

$("#a").className

hoặc $ ( "# a") [0] .className như className là chỉ có sẵn trên phần tử DOM và không phải là đối tượng jQuery
Naeem Sarfraz

đây là nhận xét cho câu trả lời của một số người, không phải câu trả lời
TJ

0

Tôi cũng sử dụng gạch nối'- 'và các chữ số cho tên lớp. Vì vậy, phiên bản của tôi bao gồm '\ d-'

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.\d-*?\b/g, '');

0
(function($)
{
    return this.each(function()
    {
        var classes = $(this).attr('class');

        if(!classes || !regex) return false;

        var classArray = [];

        classes = classes.split(' ');

        for(var i=0, len=classes.length; i<len; i++) if(!classes[i].match(regex)) classArray.push(classes[i]);

        $(this).attr('class', classArray.join(' '));
    });
})(jQuery);

-6
$("#element").removeAttr("class").addClass("yourClass");

3
Tôi không nghĩ rằng bạn đọc câu hỏi rất tốt. Người dùng không hỏi về việc chỉ cần xóa một lớp và thêm một lớp khác.
Andrew Barber

1
@Andrew Barber: bạn nói đúng, đây không phải là câu trả lời đúng, nhưng chuyên giak8 đã gợi ý cách xóa tất cả các lớp (removeAttr), không chỉ một lớp duy nhất;)
Tilt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.