DOM attribute manipulation
DOM attribute manipulation is a core part of interacting with web elements in JavaScript, allowing direct reading, modification, or deletion of element attributes. Attribute operations are not limited to standard HTML attributes but also include custom attributes, data attributes, and dynamic attribute management.
Basic Methods for Accessing Attributes
DOM elements provide multiple ways to access and manipulate attributes. The most basic methods are using dot notation or square brackets:
const element = document.getElementById('myElement');
console.log(element.id); // Access via dot notation
console.log(element['className']); // Access via square brackets
These methods work for standard HTML attributes like id
, class
, href
, etc. However, note that some attribute names may conflict with JavaScript reserved words (e.g., class
), in which case square bracket syntax is safer.
General Attribute Manipulation Methods
DOM provides more generic attribute manipulation APIs:
-
getAttribute()
Retrieves the current value of any attribute, including custom ones:const value = element.getAttribute('data-custom');
-
setAttribute()
Sets an attribute value, creating it if it doesn't exist:element.setAttribute('aria-expanded', 'true');
-
removeAttribute()
Completely removes an attribute:element.removeAttribute('disabled');
-
hasAttribute()
Checks if an attribute exists:if (element.hasAttribute('required')) { // Handle required field logic }
Special Handling for Boolean Attributes
Boolean attributes like disabled
and checked
have unique behaviors:
// Correct approach
checkbox.checked = true; // Direct DOM property manipulation
element.setAttribute('disabled', ''); // HTML standard syntax
// Incorrect example
element.setAttribute('checked', 'true'); // Won't work as expected
Dataset for Custom Data Attributes
HTML5's data-*
attributes can be conveniently accessed via the dataset
object:
<div id="user" data-user-id="123" data-registration-date="2023-01-01"></div>
const userElement = document.getElementById('user');
console.log(userElement.dataset.userId); // "123"
userElement.dataset.lastLogin = new Date().toISOString();
Note: Dataset properties automatically convert to camelCase (e.g., data-registration-date
becomes registrationDate
).
Style Manipulation
Inline styles can be directly manipulated via the style
property:
element.style.backgroundColor = '#f00';
element.style.setProperty('--primary-color', '#00f'); // CSS variables
To get computed styles, use:
const styles = window.getComputedStyle(element);
console.log(styles.getPropertyValue('font-size'));
Class Management with classList
Compared to directly manipulating the className
string, classList
offers finer control:
element.classList.add('active', 'highlight');
element.classList.remove('inactive');
element.classList.toggle('visible', shouldShow);
console.log(element.classList.contains('primary'));
Difference Between Attributes and Properties
DOM elements distinguish between HTML attributes and DOM properties:
<input id="search" value="Default value">
const input = document.getElementById('search');
input.value = 'New value'; // Modifies DOM property
console.log(input.getAttribute('value')); // Still returns "Default value"
Synchronization behavior depends on the attribute type. For example, value
is one-way synchronized (attribute → DOM), while id
is two-way synchronized.
Performance Considerations for Custom Attributes
Frequent attribute manipulation may trigger reflows/repaints. Optimization tips:
// Poor practice
for (let i = 0; i < 100; i++) {
element.setAttribute('data-index', i);
}
// Better approach
const value = element.getAttribute('data-original');
// Process in memory...
element.setAttribute('data-modified', processedValue);
Form Attribute Manipulation
Form controls have special properties and methods:
const select = document.querySelector('select');
select.selectedIndex = 2; // Set selected item
select.options[1].setAttribute('selected', ''); // Alternative method
const fileInput = document.getElementById('avatar');
console.log(fileInput.files[0]?.name);
ARIA Attribute Handling
Accessibility attributes should be manipulated via dedicated methods:
// Better than direct setAttribute
element.ariaHidden = 'true';
console.log(element.ariaLabel);
Dynamic Attribute Observation
Use MutationObserver to monitor attribute changes:
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.attributeName === 'data-status') {
console.log('Status changed:', element.dataset.status);
}
});
});
observer.observe(element, { attributes: true });
Enumerating Attributes
Iterate over all element attributes:
// Get standard properties
for (let prop in element) {
if (typeof element[prop] !== 'function') {
console.log(prop, element[prop]);
}
}
// Get all HTML attributes
Array.from(element.attributes).forEach(attr => {
console.log(`${attr.name}: ${attr.value}`);
});
Attribute Naming Conventions
Common naming style conversions:
// Convert HTML kebab-case to JavaScript camelCase
function htmlToJS(name) {
return name.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
}
// Reverse conversion
function jsToHTML(name) {
return name.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`);
}
Copying Attributes Between Elements
Copy attributes to a new element:
function cloneAttributes(source, target) {
Array.from(source.attributes).forEach(attr => {
target.setAttribute(attr.name, attr.value);
});
}
Attribute Validation
Validate attribute values before setting:
function setValidatedAttribute(element, name, value) {
if (name === 'maxlength' && !Number.isInteger(value)) {
throw new Error('maxlength must be an integer');
}
element.setAttribute(name, value);
}
Attributes and Events
Some attribute changes trigger events:
element.addEventListener('disabledStateChange', e => {
console.log('Disabled state changed');
});
// Custom attribute change event
const event = new CustomEvent('attributeChange', {
detail: { attributeName: 'data-loaded' }
});
element.dispatchEvent(event);
Browser Compatibility
Handling browser differences in attribute manipulation:
// Legacy IE class handling
if ('classList' in document.documentElement === false) {
Object.defineProperty(HTMLElement.prototype, 'classList', {
get() {
return {
contains: function(className) {
return this.className.split(/\s+/).includes(className);
},
// Implement other methods...
};
}
});
}
Attributes in Shadow DOM
Special handling in Shadow DOM:
class MyElement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `<div part="inner"></div>`;
}
static get observedAttributes() {
return ['theme'];
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'theme') {
this.shadowRoot.querySelector('div').setAttribute('theme', newValue);
}
}
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn