您现在的位置: 365建站网 > 365文章 > HTML 元素转 JavaScript 对象:DOM 属性、dataset 与 HTML 字符串解析

HTML 元素转 JavaScript 对象:DOM 属性、dataset 与 HTML 字符串解析

文章来源:365jz.com 点击数:11 更新时间:2024-05-21 13:38

把 HTML 元素变成 JS 可操作的“对象”,靠的是 DOM(文档对象模型)——浏览器把标签解析成节点树,每个节点都是一个对象,有属性、方法与事件。这跟“把 HTML 字符串转成 JSON 对象”是两件完全不同的事,很多新手会混。本文把两套做法都写清楚。

将HTML元素转化为JavaScript对象模型

一、DOM 方向:把页面元素当对象用

元素对象自带的信息非常丰富:

const el = document.querySelector('#card');

const info = {
tag: el.tagName, // ‘DIV’
id: el.id,
classes: […el.classList], // [‘card’,‘active’]
attrs: Object.fromEntries(
[…el.attributes].map(a => [a.name, a.value])
),
dataset: { …el.dataset }, // data-* 属性集合
rect: { // 尺寸与位置
w: el.offsetWidth, h: el.offsetHeight,
x: el.offsetLeft, y: el.offsetTop
},
styles: getComputedStyle(el), // 计算后样式(只读为主)
text: el.textContent.trim(),
html: el.innerHTML,
childrenCount: el.children.length
};
console.log(info);

几个要点:dataset 是 data-xxx 属性的驼峰映射(data-user-id → dataset.userId),做组件配置最常用;getComputedStyle 拿到的是渲染后的值,比 el.style 更真实;offsetLeft 相对定位父级,要页面绝对坐标用 getBoundingClientRect()。

二、把整棵树转成普通对象(自定义遍历)

浏览器不会把整页给你一个纯数据对象,需要自己走:

function toNode(el) {
  return {
    tag: el.tagName.toLowerCase(),
    attrs: Object.fromEntries([...el.attributes].map(a => [a.name, a.value])),
    text: el.childElementCount ? '' : el.textContent.trim(),
    children: [...el.children].map(toNode)
  };
}
const tree = toNode(document.getElementById('app'));
JSON.stringify(tree, null, 2);

这适合做页面结构快照、模板调试、简易渲染器。注意它只走 element 节点,忽略文本与注释节点;要完整表达需改用 NodeFilter 遍历 childNodes。

三、字符串方向:HTML 文本 → 对象/JSON

如果拿到的是后端返回的 HTML 字符串,先解析成节点再取数据:

const html = `
  <ul id="menu">
    <li data-id="1" class="on">首页</li>
    <li data-id="2">文档</li>
  </ul>`;

// 方式1:DOMParser(推荐,不会执行脚本)
const doc = new DOMParser().parseFromString(html, ‘text/html’);
const items = […doc.querySelectorAll(‘#menu li’)]
.map(li => ({ id: +li.dataset.id, label: li.textContent, on: li.classList.contains(‘on’) }));

// 方式2:template 元素(同样安全)
const tpl = document.createElement(‘template’);
tpl.innerHTML = html;
const first = tpl.content.querySelector(‘li’);

安全红线:不要用 div.innerHTML = html 解析不可信内容再插入页面。HTML 里的 <img onerror>、<script> 会造成 XSS;DOMParser 与 <template> 生成的节点不在文档中,脚本不会执行,是相对安全的解析方式。需要展示富文本时,还要过一遍净化库(如 DOMPurify)。

四、属性/参数转对象的三个常用小工具

// 1. URL 查询串 → 对象
const query = Object.fromEntries(new URLSearchParams(location.search));

// 2. 表单 → 对象
const form = Object.fromEntries(new FormData(formEl).entries());

// 3. data-* → 对象(含 JSON 值)
// <div data-config=‘{“limit”:10}’>
const cfg = JSON.parse(el.dataset.config);

FormData + Object.fromEntries 是收集表单最省事的方式,多选框与文件字段要注意取值差异(同名多值用 getAll())。

五、反向:对象 → HTML

function render(data) {
  const li = document.createElement('li');
  li.dataset.id = data.id;
  li.textContent = data.label;            // 用 textContent,天然防 XSS
  li.className = data.on ? 'on' : '';
  return li;
}
const ul = document.getElementById('menu');
ul.replaceChildren(...list.map(render));   // 一次性替换,性能优于循环 append

能不用 innerHTML += 就不用:每次 += 都会重新解析并销毁已有节点,既慢又可能把用户输入当 HTML 执行。

六、常见问题 FAQ

问:el.style.width 读到空字符串?
答:它只反映行内样式,样式表里的值要用 getComputedStyle(el).width。

问:innerHTML 与 outerHTML 区别?
答:innerHTML 是元素内部内容,outerHTML 包含元素自身标签;给 outerHTML 赋值会替换整个节点,之前的引用失效。

问:能不能直接把 DOM 对象 JSON.stringify?
答:不能,DOM 节点含循环引用会抛 Converting circular structure to JSON,必须像第二节那样手工挑字段。

归纳:把 HTML 元素当对象用,核心是 属性(attributes/dataset/classList)+ 布局(offset*/getBoundingClientRect)+ 样式(getComputedStyle)+ 内容(textContent/innerHTML) 四组 API;要把 HTML 字符串变对象,用 DOMParser 或 <template> 解析后再取值;渲染输出时用 textContent 而不是拼接 innerHTML,防 XSS 靠这个习惯。

生产内容,同时打通搜索引擎(SEO)与AI搜索引擎(GEO)流量入口的软件! 点击进入365建站器 »