You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用现代DOM方法替代document.write处理多对象数组生成目录

解决DOM操作替换document.write+处理数组属性对象数组的NaN问题

嘿,我懂你遇到的麻烦——想用现代DOM方法替代老旧的document.write生成数学目录,结果用嵌套循环加innerHTML +=的时候碰到了NaN错误对吧?我来帮你拆解问题,再给你几个可行的实现方案。

先说说NaN错误的大概率原因

你碰到的NaN,基本是因为字符串拼接时混入了非字符串/未定义的值,比如某个对象的属性不是数组、数组里存在undefined,或者循环时不小心把非数值类型和数值做了运算(比如html += 100 + undefined就会得到NaN)。另外如果你的数组属性长度不一致,也可能导致遍历到不存在的索引,拿到undefined进而引发拼接异常。

方案1:安全的innerHTML拼接实现

这个方案适合你已经确定所有HTML内容都是可控、无风险的场景,代码简洁易读:

首先在HTML里准备好容器:

<div id="mathematik-inhaltsverzeichnis"></div>

然后写JS代码:

// 获取目标容器,先判断是否存在避免报错
const container = document.getElementById('mathematik-inhaltsverzeichnis');
if (!container) return;

// 定义通用渲染函数,处理单个目录数组
function renderInhaltsverzeichnis(dirArray) {
  let sectionHtml = '';
  
  dirArray.forEach(item => {
    // 解构出所有需要的数组属性
    const { kapitel, name, a_href, buch } = item;
    
    // 先做合法性校验:必须都是数组,且长度一致
    if (!Array.isArray(kapitel) || !Array.isArray(name) || !Array.isArray(a_href) || !Array.isArray(buch)) {
      console.warn('跳过格式错误的目录项:属性非数组', item);
      return;
    }
    if (kapitel.length !== name.length || name.length !== a_href.length || a_href.length !== buch.length) {
      console.warn('跳过格式错误的目录项:数组长度不匹配', item);
      return;
    }
    
    // 遍历数组元素,拼接每一项的HTML
    sectionHtml += '<div class="kapitel-section">';
    kapitel.forEach((kapitelTitle, index) => {
      // 用|| ''兜底undefined,避免拼接时出现NaN
      const book = buch[index] || '';
      const linkHref = a_href[index] || '';
      const linkContent = name[index] || '';
      
      sectionHtml += `
        <div class="dir-entry">
          <span class="book-label">${book}</span>
          <h4 class="chapter-title">${kapitelTitle}</h4>
          <a href="#${linkHref}" class="dir-link">${linkContent}</a>
        </div>
      `;
    });
    sectionHtml += '</div>';
  });
  
  // 把拼接好的HTML插入容器
  container.innerHTML += sectionHtml;
}

// 调用函数渲染所有数学目录
renderInhaltsverzeichnis(inhaltsverzeichnis_symbole_mathematik);
renderInhaltsverzeichnis(inhaltsverzeichnis_Beweisfuehrung_mathematik);
renderInhaltsverzeichnis(inhaltsverzeichnis_mathematik);

方案2:更安全的DOM元素创建方式(推荐)

如果你的目录内容里包含用户输入或者不可控的HTML,用innerHTML有XSS风险,这时候直接创建DOM元素更稳妥,也从根源上避免了字符串拼接导致的NaN问题:

const container = document.getElementById('mathematik-inhaltsverzeichnis');
if (!container) return;

function renderInhaltsverzeichnis(dirArray) {
  dirArray.forEach(item => {
    const { kapitel, name, a_href, buch } = item;
    
    // 同样先做合法性校验
    if (!Array.isArray(kapitel) || !Array.isArray(name) || !Array.isArray(a_href) || !Array.isArray(buch)) {
      console.warn('跳过格式错误的目录项:属性非数组', item);
      return;
    }
    if (kapitel.length !== name.length || name.length !== a_href.length || a_href.length !== buch.length) {
      console.warn('跳过格式错误的目录项:数组长度不匹配', item);
      return;
    }
    
    // 创建章节组容器
    const sectionDiv = document.createElement('div');
    sectionDiv.classList.add('kapitel-section');
    
    kapitel.forEach((kapitelTitle, index) => {
      // 创建单个条目容器
      const entryDiv = document.createElement('div');
      entryDiv.classList.add('dir-entry');
      
      // 书籍标签
      const bookSpan = document.createElement('span');
      bookSpan.classList.add('book-label');
      bookSpan.textContent = buch[index] || '';
      entryDiv.appendChild(bookSpan);
      
      // 章节标题
      const chapterH4 = document.createElement('h4');
      chapterH4.classList.add('chapter-title');
      chapterH4.textContent = kapitelTitle || '';
      entryDiv.appendChild(chapterH4);
      
      // 链接(支持HTML内容)
      const link = document.createElement('a');
      link.classList.add('dir-link');
      link.href = `#${a_href[index] || ''}`;
      // 如果name[index]是HTML字符串,用innerHTML;否则用textContent更安全
      if (name[index] && name[index].includes('<')) {
        link.innerHTML = name[index];
      } else {
        link.textContent = name[index] || '';
      }
      entryDiv.appendChild(link);
      
      sectionDiv.appendChild(entryDiv);
    });
    
    container.appendChild(sectionDiv);
  });
}

// 渲染所有目录
renderInhaltsverzeichnis(inhaltsverzeichnis_symbole_mathematik);
renderInhaltsverzeichnis(inhaltsverzeichnis_Beweisfuehrung_mathematik);
renderInhaltsverzeichnis(inhaltsverzeichnis_mathematik);

关键注意点

  1. 合法性校验:一定要先检查每个对象的属性是否为数组,且数组长度一致,避免遍历到不存在的索引拿到undefined
  2. 兜底处理:对每个可能为undefined的变量用|| ''兜底,确保拼接的都是字符串类型,从根源上避免NaN。
  3. 安全优先:如果内容不可控,优先用DOM元素创建的方式,不要用innerHTML

内容的提问来源于stack exchange,提问作者Eduard Tester

火山引擎 最新活动