Как добавить несколько дочерних элементов в DOM и отобразить их, используя ванильный javascript?

Я пытаюсь вставить некоторые значки SVG в дом, но SVG (родительский узел) всегда заменяется на использование (дочерний узел). Кто-нибудь поможет мне разобраться?

Исходный код Изображение здесь

Кодировать здесь

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 );

} );

Этот снимок работает здесь

Все равно не будет отображаться в DOM. На самом деле они добавляются, потому что, когда я навожу их в инспекторе, они есть, но не видны.

ВТОРОЕ ОБНОВЛЕНИЕ КОДА

Похоже, вам нужно создать какой-то «поддельный» элемент внутри моего svg> use> «поддельный элемент», например 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> 

Проверенный код, показывающий автоматически созданный теневой элемент

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. Создал тень, а также добавил ее как дочерний элемент к элементу использования.

Проблема все еще существует, пока при добавлении тени к элементу использования ни DOM, ни консоль фактически ничего не отображают!


person Evan    schedule 17.04.2019    source источник
comment
Почему вы добавляете два раза?   -  person El.    schedule 17.04.2019
comment
Может быть, вы хотите использовать `appendChild(svg)`?   -  person Jonas Wilms    schedule 17.04.2019
comment
Вы не можете манипулировать DOM iframe таким образом. Ваш код запускается в iframe всякий раз, когда вы используете Codepen.   -  person FirstIndex    schedule 17.04.2019
comment
Проблема происходит не только в ручке кода.   -  person Evan    schedule 17.04.2019
comment
@Эл. я просто добавляю дочерний элемент использования к родительскому элементу svg, а затем добавляю дочерний элемент svg, который является родителем используемого дочернего элемента, к родительскому элементу techs_icons. так что это немного похоже на использование techs_icons › svg ›   -  person Evan    schedule 17.04.2019
comment
Нет, вы нигде не добавляете svg? минимально воспроизводимый пример!   -  person Jonas Wilms    schedule 17.04.2019
comment
1. удалить устаревший код. 2. использовать createElementNS()   -  person Supersharp    schedule 19.04.2019
comment
@Supersharp, что ты имеешь в виду под устаревшим кодом, мой друг? :D   -  person Evan    schedule 19.04.2019
comment
@ Эван, 1-я часть неверна, и вы исправили ее обновлением => удалите ее.   -  person Supersharp    schedule 19.04.2019


Ответы (3)


Элементы SVG не являются стандартным HTML, поэтому вам необходимо указать пространство имен SVG в методе createElementNS():

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>
person Supersharp    schedule 19.04.2019

Я поиграл с вашим 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.

person igreka    schedule 17.04.2019
comment
Проблема, мой друг, в том, что я уже протестировал спрайты, и они работают нормально! Я имею в виду, что ранее я жестко закодировал все значки, и теперь я пытаюсь добавить их динамически в DOM. - person Evan; 17.04.2019
comment
Где я могу получить доступ к файлу .svg в вашем Codepen? Я не мог найти его. Может быть, я мог бы исследовать немного больше с ним на руках. - person igreka; 17.04.2019
comment
Привет, @igreka, я только что обновил пост. Он включает также исходный код svg. - person Evan; 18.04.2019

person    schedule
comment
также вы используете tech_icons.appendChild( use ).appendChild( use );// используйте дважды, я думаю, вы должны использовать svg и использовать - person vishnu prasath; 17.04.2019
comment
Это имеет синтаксические ошибки и не отвечает на вопрос? - person Jonas Wilms; 17.04.2019
comment
Может быть, вы хотите использовать `appendChild(svg)`? вот что я имел в виду под комментарием, как ты сказал ранее @jonas wilms - person vishnu prasath; 17.04.2019
comment
Да, это опечатка. Вопрос должен быть закрыт как таковой. В этом вопросе нет долгосрочной ценности. - person Jonas Wilms; 17.04.2019