JQuery .hasClass для нескольких значений в инструкции if

81

У меня есть простой оператор if как таковой:

if ($('html').hasClass('m320')) {

// do stuff 

}

Это работает, как ожидалось. Однако я хочу добавить больше классов, чтобы if statementпроверить, присутствует ли какой-либо из классов в <html>теге. Мне нужно, чтобы не все, а просто наличие хотя бы одного класса, а может быть и больше.

Мой вариант использования состоит в том, что у меня есть классы (например m320, m768), добавленные для различной ширины окна просмотра, поэтому я хочу выполнить определенный JQuery только в том случае, если это определенная ширина (класс).

Вот что я пробовал до сих пор:

1.

if ($('html').hasClass('m320', 'm768')) {

// do stuff 

}

2.

if ($('html').hasClass('m320')) || ($('html').hasClass('m768')) {

 // do stuff 

}

3.

 if ($('html').hasClass(['m320', 'm768'])) {

 // do stuff 

    }

Однако, похоже, ничего из этого не работает. Не уверен, что делаю неправильно, но, скорее всего, мой синтаксис или структура.

Дэнни Энгландер
источник
1
Вместо того чтобы гадать, как работает API, вам следует прочитать документацию. api.jquery.com/hasclass Кроме того, консоль разработчика должна быть под рукой / открыта во время разработки.
скалы безумия
возможный дубликат jQuery hasClass () - проверьте наличие более одного класса
Стефан Вайнхольд

Ответы:

74

Во второй попытке у вас только что были неправильные скобки.

var $html = $("html");

if ($html.hasClass('m320') || $html.hasClass('m768')) {

  // do stuff 

}
Джеймс Монтань
источник
6
Вам действительно следует кэшировать $('html')переменную вместо того, чтобы искать ее несколько раз.
epascarello
1
@epascarello Совершенно верно, обновляя ответ для потомков.
Джеймс Монтань
163

Вы можете использовать is()вместо hasClass():

if ($('html').is('.m320, .m768')) { ... }
Elclanrs
источник
3
Да hasClass(), вероятно, быстрее, но в is()большинстве случаев намного удобнее
elclanrs
1
Кстати, здесь мы можем увидеть тесты производительности is()иhasClass()
Jignesh Gohel
1
Так что он намного медленнее, но в целом очень быстрый. Если сканируется всего несколько элементов, это не имеет большого значения для более чистого кода.
jerclarke
28

Ради интереса я написал небольшой дополнительный метод jQuery, который будет проверять одно из нескольких имен классов:

$.fn.hasAnyClass = function() {
    for (var i = 0; i < arguments.length; i++) {
        if (this.hasClass(arguments[i])) {
            return true;
        }
    }
    return false;
}

Затем в вашем примере вы можете использовать это:

if ($('html').hasAnyClass('m320', 'm768')) {

// do stuff 

}

Вы можете передать сколько угодно имен классов.


Вот расширенная версия, которая также позволяет передавать несколько имен классов, разделенных пробелом:

$.fn.hasAnyClass = function() {
    for (var i = 0; i < arguments.length; i++) {
        var classes = arguments[i].split(" ");
        for (var j = 0; j < classes.length; j++) {
            if (this.hasClass(classes[j])) {
                return true;
            }
        }
    }
    return false;
}

if ($('html').hasAnyClass('m320 m768')) {
    // do stuff 
}

Рабочая демонстрация: http://jsfiddle.net/jfriend00/uvtSA/

jfriend00
источник
Отлично, работает хорошо ... кроссбраузерность тоже! Проверено на FF и IE.
crmpicco
Я сделал небольшую модификацию, чтобы он соответствовал соглашениям jQuery для .addClass и .removeClass (). ( stackoverflow.com/a/14887517/170456 )
CyberMonk
25

Это может быть другое решение:

if ($('html').attr('class').match(/m320|m768/)) {  
  // do stuff   
}  

согласно jsperf.com, это тоже довольно быстро.

Коля
источник
Очень красиво, намного быстрее!
Филип
9
Это также будет соответствовать классу ZZZm320WWW и подобным. Попробуйте ... match (/ \ b (m320 | m768) \ b /), где \ b соответствуют началу и концу слова.
Хуан Ланус
просто чтобы продолжить (7 лет спустя :)). Это отлично работает, но если элемент html, который вы определяете, не имеет никаких классов, он выдаст ошибку «Невозможно прочитать свойство" соответствует "неопределенному». В этом случае проверьте, есть ли у элемента даже атрибут «класс» (или проверьте, чтобы атрибут «класс» не был нулевым).
Саня
5

Для тех, кто интересуется некоторыми различными аспектами производительности со всеми этими различными параметрами, я создал здесь пример jsperf: jsperf

Короче говоря, используя element.hasClass('class') - самое быстрое.

Следующий лучший вариант - использовать elem.hasClass('classA') || elem.hasClass('classB') . Примечание по этому поводу: порядок имеет значение! Если более вероятно, что будет найден класс classA, сначала укажите его! Операторы условия ИЛИ возвращаются, как только выполняется одно из них.

Наихудшей производительностью было использование element.is('.class').

В jsperf также перечислены функция CyberMonk и решение Коли .

Райан Штеффер
источник
Очень интересно! Я понятия не имел о jsperf. Спасибо за иллюстрации всех вариантов.
Дэнни Энгландер
3

Вот небольшой вариант ответа, предложенного jfriend00:

$.fn.hasAnyClass = function() {
    var classes = arguments[0].split(" ");
    for (var i = 0; i < classes.length; i++) {
        if (this.hasClass(classes[i])) {
            return true;
        }
    }
    return false;
}

Позволяет использовать тот же синтаксис, что и .addClass () и .removeClass (). например, .hasAnyClass('m320 m768') нуждается в противопульной защите, конечно, поскольку это предполагает хотя бы один аргумент.

CyberMonk
источник
0
var classes = $('html')[0].className;

if (classes.indexOf('m320') != -1 || classes.indexOf('m768') != -1) {
    //do something
}
аденео
источник
1
Если вы собираетесь это сделать, зачем вообще использовать jquery для получения элемента?
Джеймс Монтань
Ну, я бы не стал, но, по крайней мере, он получает классы только один раз? Это казалось таким скучным без небольшого количества jQuery, поэтому я заменил getElementsByTagName на некоторую магию jQ специально для вас!
adeneo
0

Метод hasClass принимает в качестве аргумента массив имен классов, вы можете сделать что-то вроде этого:

$(document).ready(function() {
function filterFilesList() {
    var rows = $('.file-row');
    var checked = $("#filterControls :checkbox:checked");

    if (checked.length) {
        var criteriaCollection = [];

        checked.each(function() {
            criteriaCollection.push($(this).val());
        });

        rows.each(function() {
            var row = $(this);
            var rowMatch = row.hasClass(criteriaCollection);

            if (rowMatch) {
                row.show();
            } else {
                row.hide(200);
            }
        });
    } else {
        rows.each(function() {
            $(this).show();
        });
    }
}

    $("#filterControls :checkbox").click(filterFilesList);
    filterFilesList();
});
Рон Симс II
источник
0

Это на тот случай, если вам нужны оба класса. Для логики или или просто используйте ||

$('el').hasClass('first-class') || $('el').hasClass('second-class')

Не стесняйтесь оптимизировать по мере необходимости

qwerty_igor
источник
1
Это не правильно. Первый приведенный вами пример работает только потому, что метод плохо очищает ввод и считает, что вся строка является именем класса. Это не сработает, если классы расположены в другом порядке или расположены не рядом друг с другом. См. Пример: jsfiddle.net/0d57ekty
MightyPork
@MightyPork, спасибо за проверку. ты прав, его следует использовать только для каждого класса
qwerty_igor
-1

Попробуй это:

if ($('html').hasClass('class1 class2')) {

// do stuff 

}
Роберт Лозинский
источник
Добро пожаловать в Stack Overflow! Пожалуйста, объясните, почему этот код помогает OP. Это поможет дать ответ будущим зрителям. См. « Как ответить» для получения дополнительной информации.
Обезьяна-еретик