代码之家  ›  专栏  ›  技术社区  ›  DoD

用js构建一个html<math>元素并不能使其正确呈现

  •  2
  • DoD  · 技术社区  · 2 年前

    这个 <math> 元素在手工编写时按预期工作,但在使用js动态创建时不能正确渲染:

    let math = document.createElement('math');
    math.setAttribute('display', 'block');
    
    let mfrac = document.createElement('mfrac');
    let ms1 = document.createElement('ms');
    let ms2 = document.createElement('ms');
    
    ms1.textContent = 'this';
    ms2.textContent = 'doesn\'t';
    
    mfrac.appendChild(ms1);
    mfrac.appendChild(ms2);
    
    math.appendChild(mfrac);
    
    document.body.appendChild(math);
    <!DOCTYPE html>
    <html>
    
    <body>
      <math display="block">
            <mfrac>
                <ms>this</ms>
                <ms>works</ms>
            </mfrac>
        </math>
    </body>
    
    </html>

    未渲染分数的屏幕截图:

    enter image description here

    正在更新现有 <数学> 尽管文档在检查器中发生了更改,但通过插入新的子元素根本不会更改它们的外观。

    1 回复  |  直到 2 年前
        1
  •  3
  •   Mike 'Pomax' Kamermans    2 年前

    math 它的相关元素是两个元素之一“它现在在HTML规范中,但JS仍然只允许您将它们构建为名称空间的XML元素”(另一个是 svg ),所以您需要使用 createElementNS http://www.w3.org/1998/Math/MathML 命名空间。如果你不这样做,它就不算是“真正的”数学元素。

    const MathNS = `http://www.w3.org/1998/Math/MathML`;
    const createMathElement = (tag) => document.createElementNS(MathNS, tag);
    
    const math = createMathElement(`math`);
    math.setAttribute(`display`, `block`);
    
    let mfrac = createMathElement(`mfrac`);
    let ms1 = createMathElement(`ms`);
    let ms2 = createMathElement(`ms`);
    
    ms1.textContent = `this`;
    ms2.textContent = `also works`;
    
    mfrac.appendChild(ms1);
    mfrac.appendChild(ms2);
    math.appendChild(mfrac);
    
    document.body.appendChild(math);
    <!DOCTYPE html>
    <html>
    
    <body>
      <math display="block">
            <mfrac>
                <ms>this</ms>
                <ms>works</ms>
            </mfrac>
        </math>
    </body>
    
    </html>
        2
  •  0
  •   Carsten Massmann    2 年前

    正如@MikePomaxKamermans所建议的,这里是一个“单独的答案”:

    document.body.insertAdjacentHTML("beforeend",`<math display="block"><mfrac><ms>and this</ms><ms>works too!</ms></mfrac></math>`)
    
    

    const MathNS = `http://www.w3.org/1998/Math/MathML`;
    const createMathElement = (tag) => document.createElementNS(MathNS, tag);
    
    const math = createMathElement(`math`);
    math.setAttribute(`display`, `block`);
    
    let mfrac = createMathElement(`mfrac`);
    let ms1 = createMathElement(`ms`);
    let ms2 = createMathElement(`ms`);
    
    ms1.textContent = `this`;
    ms2.textContent = `also works`;
    
    mfrac.appendChild(ms1);
    mfrac.appendChild(ms2);
    math.appendChild(mfrac);
    
    document.body.appendChild(math);
    
    document.body.insertAdjacentHTML("beforeend",`<math display="block"><mfrac><ms>and this</ms><ms>works too!</ms></mfrac></math>`)
    <!DOCTYPE html>
    <html>
    
    <body>
      <math display="block">
            <mfrac>
                <ms>this</ms>
                <ms>works</ms>
            </mfrac>
        </math>
    </body>
    
    </html>

    正如Mike已经解释的那样,上面的方法是“利用DOM解析器的能力来自动判断哪些元素需要哪些命名空间。”