Adding and Removing DOM Elements

In modern frontend development, the Document Object Model (DOM) serves as the bridge connecting HTML structure with JavaScript logic. Mastering how to dynamically add and remove DOM elements is a fundamental skill for building responsive web pages and implementing interactive features. Whether you are creating simple modal alerts or constructing complex Single Page Applications (SPAs), precise manipulation of DOM elements is a core competency every developer must possess. This article delves into the key methods for manipulating the DOM using native JavaScript and demonstrates their application scenarios through practical examples.

Basic Concepts: Understanding DOM Nodes and Attributes

Before writing code, we need to clarify several core concepts. The DOM tree is a hierarchical structure composed of element nodes, text nodes, and attribute nodes. When we say "add an element," we are essentially creating a new DOM node object in memory and inserting it into the existing document flow; conversely, "removing an element" involves deleting that node and its child nodes from a specific location within the DOM tree.

Manipulating the DOM typically involves two main steps: first, creating a new element using document.createElement(), and then positioning and inserting it into the page using various methods. Common attributes include innerHTML (used for setting HTML content), innerText (text only), and various CSS style properties. Understanding these basic concepts helps us avoid common pitfalls when writing code later, such as XSS attack risks or performance bottlenecks.

Common Methods for Adding DOM Elements

JavaScript provides multiple ways to add elements to a page, each suitable for different scenarios. The most fundamental and recommended approach is using document.createElement() in conjunction with the appendChild() method. This approach offers clear structure, ease of maintenance, and excellent handling of complex nested structures.

// Create a new div element
const newDiv = document.createElement('div');
newDiv.className = 'highlight-box';
newDiv.innerHTML = '<h3>Welcome to Learning DOM</h3><p>This is dynamically added content.</p>';

// Find the target container (e.g., the div with id "container")
const container = document.getElementById('container');

// Add the new element to the container
container.appendChild(newDiv);

In addition to appendChild(), other methods such as insertBefore(), prepend(), and append() are available for selection. Among them, insertBefore() allows us to insert a new element before an existing child node, which is very useful for adjusting element order; while prepend() and append() are special cases used to add elements to the beginning or end of a parent node, respectively.

// Insert before the first child node
const firstChild = container.firstElementChild;
container.insertBefore(newDiv, firstChild);

// Use modern API (good browser support)
container.append(newDiv); // Equivalent to appendChild but more semantic

Strategies and Precautions for Removing DOM Elements

There are also multiple implementation methods for removing DOM elements, and the choice of method depends on specific business requirements. The most commonly used method is remove(), which can directly remove a child node from its parent and clean up related references. Another approach is using parentNode.removeChild(), which may be more stable in certain older browsers or special scenarios.

It is crucial to note that before removing an element, you must verify the status of the element and its child nodes. If the element contains event listeners or other dynamic data internally, a simple removal operation might lead to memory leaks or logical errors. Additionally, when performing batch deletions, pay attention to performance optimization to avoid frequent reflows (Reflow).

// Directly remove the element
const targetElement = document.querySelector('.old-item');
targetElement.remove();

// Or use the traditional removeChild method
if (targetElement.parentNode) {
    targetElement.parentNode.removeChild(targetElement);
}

Practical Case: Building an Interactive To-Do List

To more intuitively demonstrate the combined application of adding and removing DOM elements, we can build a simple To-Do List example. In this scenario, users input tasks and click a button to add new items; clicking the "Complete" button removes them from the list.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>DOM Operation Practice - To-Do List</title>
</head>
<body>
    <div id="app">
        <input type="text" id="taskInput" placeholder="Enter new task..." />
        <button id="addBtn">Add Task</button>
        <ul id="taskList"></ul>
    </div>

    <script>
        const input = document.getElementById('taskInput');
        const addBtn = document.getElementById('addBtn');
        const list = document.getElementById('taskList');

        // Function to add a task
        function addTask() {
            const text = input.value.trim();
            if (!text) return;

            // Create the list item element
            const li = document.createElement('li');
            li.textContent = text;
            
            // Create the delete button
            const span = document.createElement('span');
            span.innerHTML = '🗑️';
            span.style.cursor = 'pointer';
            span.style.color = '#ff4d4f';

            // Bind the delete event
            span.onclick = function() {
                li.remove();
            };

            // Add the button to the list item
            li.appendChild(span);

            // Add the list item to the list
            list.appendChild(li);

            // Clear the input field
            input.value = '';
        }

        // Event listeners
        addBtn.addEventListener('click', addTask);
        input.addEventListener('keypress', function(e) {
            if (e.key === 'Enter') {
                addTask();
            }
        });
    </script>
</body>
</html>

Through the code above, we have implemented complete CRUD logic. When a user inputs a task and clicks the button, the system dynamically creates li elements along with their child nodes and inserts them into the <ul>; when the user clicks the trash icon, the corresponding li is immediately removed from the DOM tree. This mode not only enhances user experience but also demonstrates the powerful capabilities of DOM operations in building interactive interfaces.

Best Practices and Performance Optimization Suggestions

In real-world projects, blindly and frequently manipulating the DOM can lead to a decline in page performance. Browsers perform Reflow (重排) and Repaint (重绘) when modifying the DOM tree, which are costly operations. Therefore, it is recommended to follow these principles:

  • Batch Operations: Merge multiple DOM operations into a single execution as much as possible to reduce the number of triggers.
  • Use Virtual Lists: For long list scenarios, adopt virtual scrolling technology to render only elements within the visible area.
  • Avoid Inline Styles: Try to control styles through CSS class names rather than directly modifying style attributes in JS.
  • Throttle and Debounce: Combine debounce or throttle mechanisms with high-frequency events (such as input or scrolling) to reduce DOM update frequency.

In summary, proficiency in adding and removing DOM elements is a basic skill for frontend developers. By understanding the underlying principles, mastering common methods, and adhering to performance optimization principles, we can build web applications that are both efficient and aesthetically pleasing.