首页 飞机号购买自助下单官网内容详情

三、修改节点:动手术的核心操作

2026-04-03 2 飞机号购买网站

你可曾有过这般好奇,当你于网页之上轻点那一个按钮之时,文字刹那间发生变化亦或是颜色即刻进行切换,其背后究竟是怎样一番状况,实际上浏览器并无什么神奇法术的,它仅仅是把HTML代码改变成为了一棵肉眼看不见的“树”罢了,然而JavaScript恰似一位技艺娴熟的外科医生一般,在这棵树上展开精准无误的操作。今日我们就要来剖析这棵树,学会运用JS给网页实施增删改查操作,从而让你彻彻底底地领会为何会说JS能够掌控网页的所有一切。

DOM树:网页的家族图谱

加载网页之际,浏览器不会径直呈现你所撰写的HTML字符串,它先是把那串字符解析成一种名为DOM树的结构。此树的根节点是document,每个HTML标签,标签内里的文字,甚至标签之上的属性,都会转变成树上的一个独立节点。比如说一个。

元素节点之中存在着一个标签,文本节点是其里面所包含的文本,属性节点系class="box"。



  
    我的网页
  
  
    

标题

一段文字

节点相互间存在着十分严格的家族关联关系,一个节点含有另一个节点,此为父子关系,处于并列情况的节点,属于兄弟关系。这般关系极为重要,缘由在于 JS 正是借助“父节点”“子节点”“兄弟节点”这些路径寻觅到你想要实施操作的目标。你能够将 DOM 树设想成一份家谱,根身为老祖宗,分支是后代,每个成员都具备自身的位置。

html
├── head
│   └── title
│       └── "我的网页"
└── body
    └── div.container
        ├── h1
        │   └── "标题"
        └── p
            └── "一段文字"

获取节点:找到你的手术位置

假若要针对网页施行手术,首先的步骤便是精确地定位到你打算进行操作的那个节点,JS给出了多种寻觅节点的办法,其中最为常用的是document.getElementById,它凭借id名径直获取唯一的元素节点,且速度是最快的,要是你期望借助CSS选择器来实施定位,document.querySelector乃是更为灵活的选择,它对任何CSS语法均予以支持。

在你有着同时去操作多个节点这样的需求之际,能够运用document.getElementsByClassName或者document.getElementsByTagName,它们所返回的是属于一个HTMLCollection集合。更为推荐的做法是使用document.querySelectorAll,它返回的乃是NodeList,其支持更为复杂的CSS选择器。拿到一个节点之后,你能够借助parentNode、children、nextSibling等属性于节点之间进行“爬树”操作,进而寻获相邻或者相关的节点。

// 根据ID(最常用)
const header = document.getElementById('header');
// 根据CSS选择器(推荐,灵活)
const container = document.querySelector('.container');
const title = document.querySelector('#title');
// 根据类名(返回集合)
const items = document.getElementsByClassName('item'); // HTMLCollection,实时更新

// 获取所有匹配的元素
const allDivs = document.querySelectorAll('div'); // NodeList,静态快照
// 根据标签名
const paras = document.getElementsByTagName('p'); // HTMLCollection

修改节点:增删改查全掌握

const container = document.querySelector('.container');
// 往上爬
const parent = container.parentNode;
// 往下爬
const firstChild = container.firstChild; // 可能是文本节点(换行)
const firstElementChild = container.firstElementChild; // 只算元素
// 找兄弟
const prev = container.previousSibling; // 可能是文本节点
const prevElement = container.previousElementSibling;
const next = container.nextElementSibling;

当寻得目标节点之后,便能够着手开展实际的操作了。用于修改内容最为频繁运用的是innerHTML以及textContent,前者能够对HTML标签予以解析,后者仅针对纯文本进行处理,更为安全且速度更快。修改属性能够借助setAttribute以及getAttribute,或者直接对属性名实施操作,例如img.src = 'new.jpg'。修改样式存在两种办法:借助style属性逐一展开修改,或者通过classList批量实现类名的切换。

新建一个节点得经历两步,头一步要借助document.createElement去打造元素节点,紧接着第二步需运用document.createTextNode来创建文本节点(又或者直接设定textContent)。往里面插入节点的法子有好多,appendChild会将新节点增添至父节点的最后一个子节点所处位置,insertBefore能够明确插入的具体位置。把节点给删掉挺容易,直接调用remove方法就行,要不然就通过父节点使用removeChild。替换节点则用replaceChild。

// 改文本内容
element.textContent = '新文本'; // 纯文本,安全
element.innerHTML = '新文本'; // 解析HTML,有XSS风险
// 改属性
element.id = 'newId';
element.className = 'newClass'; // 覆盖所有类
element.classList.add('active'); // 推荐,增删类
element.classList.remove('hidden');
element.classList.toggle('open');
// 改样式(内联样式)
element.style.color = 'red';
element.style.backgroundColor = '#f0f0f0'; // 驼峰命名

实战演练:动态待办列表

// 创建元素
const newDiv = document.createElement('div');
newDiv.textContent = '我是新来的';
// 创建文本节点(很少单独用)
const textNode = document.createTextNode('一段文字');

// 追加到最后
parent.appendChild(newDiv);
// 插入到某个子节点之前
parent.insertBefore(newDiv, referenceNode);
// 现代插入方法(更灵活)
referenceNode.before(newDiv); // 插到前面
referenceNode.after(newDiv);  // 插到后面
parent.prepend(newDiv);       // 插到父元素开头
parent.append(newDiv);        // 插到父元素末尾(类似appendChild)

依次将上面所涉及到的知识予以串联,我们着手去构建一个规模较小的待办列表。假定在页面之上存在着一个用于展现待办事项的ul元素,有一个input输入框以及一个添加按钮。当用户实施点击添加这一操作时,我们要去获取input的取值,创建出一个全新的li元素,并把文本内容放置进去,随后借助appendChild添加至ul的末尾处。同时,每一个新生成的li之中还得包含着一个删除按钮。

// 删除自己
element.remove();
// 通过父节点删除
parent.removeChild(child);

点击时,获取当前 li 节点,这一动作是删除按钮功能实现更简单的一部分,直接调用它的 remove 方法,便可从 DOM 树中摘除该节点。此小小的案例,用到了创建节点、修改文本、插入节点、删除节点全部操作。你还能够进一步扩展,例如双击待办项时,修改它的文字,或者给完成的任务添加删除线样式。而这些操作,本质上都是 JS 在动态修改那棵 DOM 树。

    const input = document.getElementById('todo-input');
    const addBtn = document.getElementById('add-btn');
    const list = document.getElementById('todo-list');
    function addTodo() {
      const text = input.value.trim();
      if (text === '') return;
      
      // 创建li元素
      const li = document.createElement('li');
      li.textContent = text;
      
      // 创建删除按钮
      const delBtn = document.createElement('button');
      delBtn.textContent = '删除';
      delBtn.onclick = function() {
        li.remove(); // 删除这一项
      };
      
      li.appendChild(delBtn);
      list.appendChild(li);
      
      input.value = ''; // 清空输入框
    }
    addBtn.addEventListener('click', addTodo);
    // 按回车也添加
    input.addEventListener('keypress', function(e) {
      if (e.key === 'Enter') addTodo();
    });

    节点集合:HTMLCollection与NodeList的区别

    好些刚开始学习的人在运用getElementsByClassName之际会发觉,所获取到的集合极为“活跃”。缘由在于HTMLCollection是实时变幻的,一旦DOM树产生变动,此集合会自行把最新的情形展现出来。举例来说,你借由getElementsByClassName获取到所有归为red类别的元素,随后移除了其中的一个,这个集合会瞬时缩减长度。

    const live = document.getElementsByClassName('item'); // 实时
    const static = document.querySelectorAll('.item'); // 静态
    // 如果你删除了一个.item元素,live会立刻变少,static还是原来的

    而querySelectorAll所返回的,是静态的NodeList,它仅仅是某个时刻的快照,后续的DOM变化并不会对其产生影响。在遍历方式方面,HTMLCollection并不具备forEach方法,你得借助Array.from将其转换为数组,或者采用传统的for循环形式来达成遍历目的。NodeList在多数现代浏览器当中支持forEach,然而为了确保相应的兼容性,并不建议直接使用,而是推荐也将其转换为数组之后再进行操作。此外,childNodes返回的是NodeList,它会涵盖文本节点以及注释节点,然而children返回的却是HTMLCollection,其仅包含元素节点。

    性能优化:减少DOM操作开销

    const fragment = document.createDocumentFragment();
    for (let i = 0; i < 1000; i++) {
      const li = document.createElement('li');
      li.textContent = i;
      fragment.appendChild(li);
    }
    list.appendChild(fragment); // 只触发一次重排

    在浏览器里,DOM操作是那种属于“重型”的操作,要是频繁去修改,就会引发页面的重排以及重绘,进而致使出现卡顿的状况,有一个关键的原则,那就是要尽可能地减少直接对DOM树进行操作的次数,当你有需要去批量插入好多新节点的时候,不要在循环当中一回回地进行appendChild操作,而是应当借助document.createDocumentFragment去创建一个虚拟的片段,先把所有的新节点添加到这个片段里面,最终一次性地插入到真实的DOM树当中。

    在进行样式修改操作之时,要尽可能地规避逐个去设定style属性这种行为,这是由于每次进行赋值都存在着触发重排的可能性。更优的做法是预先去定义好CSS类,接着运用classList.add或者classList.remove来一次性地实现切换。要是你针对一个子树的样式有着大量修改的需求,能够考虑把该子树从DOM树上暂时摘取下来,等到完成修改之后再将其放回去。除此之外,通过cloneNode进行深拷贝节点之后做离线的修改,然后再去替换原节点,这同样是一个经常会用到有的技巧。

    读完今儿的内容,你理应已然明白 JS 是怎样如同外科大夫那样精确操控 DOM 树的了。最后问你个事儿:当你打算动态造出一个含有 1000 行数据的表格时,你会采用上面哪种优化方式来确保页面不卡顿得以实现呢?欢迎于评论区分享你的想法,觉着有用就点个赞哟。

    三、修改节点:动手术的核心操作

    相关标签: # DOM # JavaScript # 网页操作 # 节点修改 # 性能优化