Нативные эквиваленты jQuery методов — Часть 2: Работа с атрибутами и свойствами
Это вторая часть постов, посвященная нативным эквивалентам jQuery методов. Если вы пропустили первую часть по выборке DOM элементов, тогда почему вы еще здесь? Переходи прямо сейчас Часть 1: Выборка DOM элементов или переходи к Часть 3: Обработчики событий или Часть 4: Создание, вставка, перемещение и удаление элементов.
В этой части мы рассмотрим манипуляции со свойствами и атрибутами — включая имена классов и data-* атрибутов.
Напомню, что атрибуты задаются с помощью HTML, а свойства относятся к DOM. Поскольку DOM элементы — это объекты, как и любые другие JavaScript объекты у них есть свойства, и они могут быть любого типа (строка, булево, функции и т.д.), в то время как атрибуты могут быть лишь строками.
Следовательно, что бы изменить свойство DOM элемента вы можете получить или задать его или при помощи точки (dot notation) или квадратных скобок, если необходимо.
// get
elem.property // or elem[propery]
// set
elem.property = 'some value'; // or elem[propery] = 'some value'
К примеру, чтобы задать элементу свойство ID:
jQuery
// get
$(elem).prop('id');
// set
$(elem).prop('id', 'myID');
Нативный JS
// get
elem.id;
// set
elem.id = 'myID';
Получение атрибутов
jQuery
$(elem).attr(name);
Нативный JS
elem.getAttribute(name);
Задание атрибутов
jQuery
$(elem).attr(name, value);
Нативный JS
elem.setAttribute(name, value);
Удаление атрибутов
jQuery
$(elem).removeAttr(name);
Нативный JS
elem.removeAttribute(name);
Помните, jQuery работает с одним или коллекциями элементов. Если вы работаете с коллекцией, которую вернули собственные методы как getElementsByClass
, querySelectorAll
и т.д., вы должны пройтись циклом и получить/задать/удалить атрибуты по отдельности.
var elems = document.querySelectorAll('.my-class');
for (i = 0; i < elems.length; ++i) {
elems[i].setAttribute(name, value);
}
И хотя намного информативнее, чем jQuery метод, родные методы, как правило, намного быстрее jsPerf.
Проверка существования атрибутов
Что самое интересное, jQuery не имеет метода для проверки элемента на определенный атрибут, пока родного метода не существует.
jQuery
var attr = $(elem).attr(name);
// attr() can return undefined or false depending on the browser
if (typeof attr !== typeof undefined && attr !== false) {
// elem has the attribute specified
}
Нативный JS
var attr = elem.hasAttribute(name); // returns a boolean
if ( attr ) {
// elem has the attribute specified
}
Дополнительно к прочтению: getAttribute, setAttribute, removeAttribute, hasAttribute
Задание имени класса
jQuery
$(elem).addClass('my-class');
Нативный JS
// for old browsers
elem.className = 'my-class'
// or if you don't want to overwrite the currently set classNames
elem.className += ' my-class'
// for not-so-old-browsers
elem.setAttribute('class', 'my-class');
Получение имени класса
jQuery
$(elem).attr('class');
Нативный JS
elem.className
Удаление имени класса
jQuery
$(elem).removeClass('my-class');
Нативный JS
Вот здесь он получается грязным, если вы поддерживаете IE <10, несуществующий родной метод для удаления отдельного класса, если элемент имеет более одного набора.
Если вам необходимо поддерживать старые браузеры, и вы уверены, что есть только один заданный класс на элементе, то используйте следующее:
elem.className = '';
// or
elem.removeAttribute('class');
В противном случае возможно вы захотите использовать некоторое строковое совпадение:
var classToRemove = 'some-class';
elem.className = elem.className.replace(new RegExp("(^|\\s)" + classToRemove.split(" ").join("|") + "(\\s|$)", "gi"), " ")
Если вы не поддерживаете IE <10, можете использовать современный classList
API. classList
имеет add
, remove
, toggle
, contains
и item
методы.
add
// add a specified class
elem.classList.add('my-class')
Метод add
только добавляет класс, если он отсутствует.
remove
// remove a specified class
elem.classList.remove('my-class')
toggle
// toggle a specified class
elem.classList.toggle('my-class')
Этот метод toggle
будет удалять класс, если он существует, или добавил его, если отсутствует.
contains
// check the element has the specified class
elem.classList.contains('my-class') // returns a boolean
Дополнительно к прочтению: classList
HTML5 Data атрибуты (data-*)
jQuery
// get
$(elem).attr('data-something')
// or
$(elem).data('data-something')
// set
$(elem).attr('data-something', 'some-value')
// or
$(elem).data('data-something', 'some-value')
Убедитесь, что вы знаете о подводных камнях, при получении и задании с помощью jQuery
data()
метода.
Нативный JS
// get
elem.getAttribute('data-something')
// set
elem.setAttribute('data-something')
Набор данных свойств доступно для современных браузеров (IE 11+). Вы можете получить и задать data-* атрибуты легко, но учтите, что data-
кусочек удаляется, а остальное пишется в camelCase («Верблюжьей» нотацией), поэтому data-some-attribute
превратится в someAttribute
.
Пример:
<div class="some-class" data-my-custom-attr="some-value"></div>
// get
elem.dataset.myCustomAttr
// set
elem.dataset.myCustomAttr = 'new-value';
// check
if ( 'myCustomAttr' in elem.dataset ) {
// elem has the attribute 'data-my-custom-attr'
}
Дополнительно к прочтению: dataset
Поддержка новый и старых браузеров
Иногда появляется непростая задача, необходимо поддерживать старые браузеры, стоит создавать свои собственные вспомогательные функции, что бы они брали на себя эту головную боль. Существует куча решений и полифилов, их можно найти в интернете, но есть те, которые я регулярно использую для манипуляций с именами классов. Они проверяют на наличие classList
API и используют его, в другом случае они используют методы, которые поддерживаются старыми браузерами.
var hasClass = function(elem,className) {
return elem.classList ? elem.classList.contains(className) : !!elem.className.match(new RegExp('(\\s|^)'+className+'(\\s|$)'));
}
var addClass = function(elem, className) {
elem.classList ? elem.classList.add(className) : hasClass(className) || (elem.className = elem.className.trim() + " " + className)
};
var removeClass = function(elem, className) {
elem.classList ? elem.classList.remove(className) : hasClass(className) && (elem.className = elem.className.replace(new RegExp("(^|\\s)" + className.split(" ").join("|") + "(\\s|$)", "gi"), " "))
};
Применение
// add a class
addClass(myElem, 'some-class');
// remove a class
removeClass(myElem, 'some-class');
// check a class exists
if (hasClass(myElem, 'some-class') {
// myElem has the class 'some-class'
}
Вот и все для этой части. Настройтесь на следующий раз, когда мы рассмотрим родные варианты обработчиков событий, как click()
, on()
, hover()
и т.д., и погрузимся в делегирование событий.