【问题标题】:How to append multiple child elements in the DOM and display them, using vanilla javascript?如何使用 vanilla javascript 在 DOM 中附加多个子元素并显示它们?
【发布时间】:2019-09-07 12:25:23
【问题描述】:

我试图在 dom 中插入一些 SVG 图标,但 SVG(父节点)总是被 use(子节点)替换。有人帮我解决吗?

Source code Image here

Codepen here

const icons = [
    "html5" ,
    "css3" ,
    "javascript" ,
    "bootstrap" ,
    "sass" ,
    "node" ,
    "mongodb" ,
    "d3" ,
    "react" ,
    "webpack" ,
    "wordpress"
];

const tech_icons = document.querySelector( "#techs__icons" );

icons.forEach( icon=> {

    const svg = document.createElement( "svg" );
    const use = document.createElement( "use" );

        svg.setAttribute( "class" , `techs__icon icon icon-${icon}` );
    use.setAttribute( "href" , `./src/images/sprites.svg#icon-${icon}` );

    tech_icons.appendChild( use ).appendChild( use );

} );

我可以成功地将它们记录在控制台中,但它们似乎没有出现在文档中。

我已经将它附加到父节点 (techs_icons) 但此时无法弄清楚!

更新代码

icons.forEach( icon=> {

    const tech_icons = document.querySelector( "#techs__icons" );

    const svg = document.createElement( "svg" );
    svg.setAttribute( "class" , `techs__icon icon icon-${icon}` );
    const use = document.createElement( "use" );
    use.setAttribute( "href" , `./src/images/sprites.svg#icon-${icon}` );

    svg.appendChild( use );

    tech_icons.appendChild( svg );

} );

This snapshot seems to work here

仍然不会显示在 DOM 中。实际上,它们被附加了,因为当我将它们悬停在检查器中时,它们在那里但不可见。

代码的第二次更新

看起来你需要在我的 svg>use>“fake element”中创建某种“fake”元素,比如 shadowRoot,我实际上不明白为什么浏览器在导入 SVG 文件时会创建这样的元素!

我在检查元素时发现了这一点,并看到浏览器实际上自动创建了那个阴影。

SVG

<symbol id="icon-html5">
   <path d="M2 0h28l-2.547 28.751-11.484 3.249-11.419-3.251-2.551-28.749zM11.375 13l-0.309-3.624 13.412 0.004 0.307-3.496-17.568-0.004 0.931 10.68h12.168l-0.435 4.568-3.88 1.072-3.94-1.080-0.251-2.813h-3.479l0.44 5.561 7.229 1.933 7.172-1.924 0.992-10.876h-12.789z"/>
 </symbol> 

Inspected code showing the auto created shadow element

const tech_icons = document.querySelector( "#techs__icons" );
const fragment = document.createDocumentFragment();

icons.forEach( icon => {

    const svg = document.createElement( "svg" );
    const use = document.createElement( "use" );
    let shadow = use.attachShadow( { mode : open } );

    svg.setAttribute( "class" , `techs__icon icon icon-${icon}` );
    use.setAttribute( "href" , `./src/images/sprites.svg#icon-${icon}` );
    shadow.appendChild( "I am a: child element inside shadowroot (svg>use>shadowroot>ME)" );

   svg.appendChild( use );

   fragment.appendChild( svg );

});

tech_icons.appendChild( fragment );

所以在这一点上回顾一下:

  1. 将 forEach() 循环的结果添加到文档片段,在该循环结束后,我将该片段作为子元素附加到真正的 DOM 元素 (.techs_info)
  2. 创建了一个阴影并将其作为子元素附加到 use 元素

问题仍然存在,当将阴影附加到 use 元素时,DOM 或控制台都没有实际显示任何内容!

【问题讨论】:

  • 为什么要追加 use 两次?
  • 也许你想使用`appendChild(svg)`?
  • 您不能以这种方式操作 iframe 的 DOM。每当您使用 Codepen 时,您的代码都会在 iframe 中运行。
  • 问题不仅仅发生在代码笔中。
  • 不,你从来没有在任何地方附加svgminimal reproducible example!

标签: javascript dom shadow-dom appendchild documentfragment


【解决方案1】:
var mylist = document.getElementById("myList")
list.forEach(item){
var node = document.createElement("LI");                 // Create a <li> node
var textnode = document.createTextNode(item);         // Create a text node
node.appendChild(textnode);                          // Append the text to <li>
mylist.appendChild(node) //Append to<Ul> id="myList"
}

【讨论】:

  • also ur using tech_icons.appendChild( use ).appendChild( use );// 使用两次我认为你应该使用 svg 并使用
  • 这有语法错误,没有回答问题?
  • 也许你想使用`appendChild(svg)`?这就是我的意思,就像你之前所说的那样@jonas wilms
  • 是的,这是一个错字。这个问题应该这样结束。这个问题没有长期价值。
【解决方案2】:

我使用这个更正的代码玩弄了你的 Codepen:


const icons = [
    "html5" ,
    "css3" ,
    "javascript" ,
    "bootstrap" ,
    "sass" ,
    "node" ,
    "mongodb" ,
    "d3" ,
    "react" ,
    "webpack" ,
    "wordpress"
];

icons.forEach( icon=> {
    const tech_icons = document.getElementById( "techs__icons" );

    const svg = document .createElementNS("http://www.w3.org/2000/svg", "svg");
    svg.setAttribute( "class" , `techs__icon icon icon-${icon}` );

    const use = document .createElementNS("http://www.w3.org/2000/svg", "use");
    use.setAttribute( "xlink:href" , `./src/images/sprites.svg#icon-${icon}` );

    svg.appendChild( use );

    tech_icons.appendChild( svg );

  console.log(tech_icons);
} );

在控制台中检查时,会创建 SVG 元素并占用文档中 DIV 中的空间,但它们似乎是空的或不可见的。所以我责怪 sprites.svg 文件。

【讨论】:

  • 我朋友的问题是我已经测试了精灵并且工作正常!我的意思是我之前对所有图标进行了硬编码,现在我正在尝试将它们动态添加到 DOM。
  • 我在哪里可以访问 Codepen 中的 .svg 文件?我找不到它。也许我可以用它进行更多调查。
  • 嘿@igreka 我刚刚更新了帖子。它还包括 svg 源代码。
【解决方案3】:

SVG 元素不是标准 HTML,因此您需要在 createElementNS() 方法中指定 SVG 命名空间:

const svg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' )
const use = document.createElementNS( 'http://www.w3.org/2000/svg', 'use' )

同样在 SVG 源文件中,您必须在 xmlns 属性中指定命名空间:

<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="icon-html5">
   <path d="M2 0h28l-2.547 28.751-11.484 3.249-11.419-3.251-2.551-28.749zM11.375 13l-0.309-3.624 13.412 0.004 0.307-3.496-17.568-0.004 0.931 10.68h12.168l-0.435 4.568-3.88 1.072-3.94-1.080-0.251-2.813h-3.479l0.44 5.561 7.229 1.933 7.172-1.924 0.992-10.876h-12.789z"/>
 </symbol> 
</svg>

【讨论】:

    【解决方案4】:
    componentDidMount (){
    
        const script = document.createElement("script");
        const script1 = document.createElement("script");
        const script2 = document.createElement("script");
    
        script.src = 'assets/js/jquery.showmore.js';
        script1.src = 'assets/js/showmore.js';
        script2.src = 'assets/js/owl-carousel.js';
        script.async = true;
        script1.async = true;
        script2.async = true;
    
        document.body.appendChild(script);
        document.body.appendChild(script1);
        document.body.appendChild(script2);
    }
    

    【讨论】:

      猜你喜欢
      • 2021-09-25
      • 2019-03-12
      • 2017-12-29
      • 1970-01-01
      • 2019-10-16
      • 2020-01-21
      • 2016-11-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多