首页 > 解决方案 > 创建新元素 JS 的更有效方法(不知道标题应该叫什么)

问题描述

我是 JavaScript 新手,我正在使用 vanilla js、html 和 css 来调查网站,用户可以在其中添加问题和选项,当他们单击按钮时,它将创建一个容器,他们可以用“tag:textarea”填充该容器. 我正在使用“createElement()”、“setAttribute()”方法来创建一个新容器。但是由于每个容器都有这么多嵌套的节点或组件,我已经编写了大量的样板代码来创建容器,而且我必须使用嵌套的“地狱”更改某些元素的 id,这变得非常难以管理。我的html代码如下:

<div id="create-question-container-id"              class="create-question-container" >
  <div id="create-question-textarea-container-id_0" class="create-question-textarea-container">
    <textarea id="create-question-textarea-id" 
              name="textareaquestion"               class="create-question-textarea" 
              cols="50" row="1" style="font-size: 20pt;">
      Untitled Question
    </textarea>
    <div id="create-answer-textarea-container-id-0" class="create-answer-textarea-container">
      <div  id="create-answer-N-container-id-0-0"   class="create-answer-N-container">
        <div                                        class="create-qeuestion-radio-outer-circle" > 
           <div                                     class="create-qeuestion-radio-innner-circle"></div>
        </div>
        <textarea id="opt1" name="textareaopt"      class="create-answer-textarea" 
                  placeholder="opt1" style="font-size: 14pt;">
        </textarea>
      </div>
    </div>
    <button onclick="addOption()"                   class="create-add-answer-btn" >
      Add Option
    </button>  
  </div>
</div>
<div                                                class="create-main-container-submit-button">
  <button onclick="clonecontainer()"                class="create-main-submit-btn" >
    Submit
  </button>
</div>

这是来自地狱的 Javascript 代码:

var answer_container = document.getElementsByClassName('create-answer-textarea-container');
//increment this one 
var answer_container_id = document.getElementById('create-answer-textarea-container-id-0');

var lastChildAnswer = answer_container[answer_container.length - 1];
var asnwer_container_list = answer_container_id.childNodes[answer_container.length];

//id of container wrapping around the question and the options named questionasnwcontain(this need to increment id)
var question_answer_container_list = document.getElementById('create-question-textarea-container-id_0')

//id of container wrapping around the questionasnwcontain(main container)
var all_question_asnwer_container = document.getElementById('create-question-container-id');

var all_question_asnwer_container_class_Name = document.getElementsByClassName('create-question-container');

var all_counter = all_question_asnwer_container.childElementCount -1;


function clonecontainer() {
  var dashed_delimeter = '-';
  var lastChildContainer =  answer_container_id.lastElementChild.getAttribute('id')
  var trimlastChild =  answer_container_id.lastElementChild.lastElementChild.getAttribute('id')
  var delimeter = 't'
  var trimlastChildSubString = trimlastChild.split(delimeter);
  var lastChildString = trimlastChildSubString[1]
  //split lastChildContainer 
  var splitted_lastChildContainer = lastChildContainer.split(dashed_delimeter)[5];
  var new_id_spliited_lastChildContainer = 'create-answer-N-container-id-' + ((parseInt(splitted_lastChildContainer)) + (all_question_asnwer_container.childElementCount -1) ) + '-0';

  //get the cloned container's child id for incremental
  var last_main_container_child = all_question_asnwer_container.lastElementChild.getAttribute('id');
  var trimlast_id = seperateWithDelimeter(last_main_container_child);
  var trimlast_new_id ='_' + (parseInt(trimlast_id[1]) +  (all_question_asnwer_container.childElementCount -1) );
  console.log(trimlast_new_id)

  //(fixed)
  var last_cloned_delimeter = '_';
  var last_cloned_container = all_question_asnwer_container.childNodes[all_question_asnwer_container_class_Name.length].getAttribute('id')
  var splitted_cloned_container = last_cloned_container.split(last_cloned_delimeter);
  var new_splitted_cloned_container_id = 'create-answer-textarea-container-id-' + ((parseInt(splitted_cloned_container[1])) + (all_question_asnwer_container.childElementCount ))  ;
  console.log(new_splitted_cloned_container_id)
  //new div fr asnwer container 
  var new_div_fr_answer_container_id = document.createElement('div');
  new_div_fr_answer_container_id.setAttribute('class' , 'create-question-textarea-container');
  new_div_fr_answer_container_id.setAttribute('id' ,'create-question-textarea-container-id' + trimlast_new_id)
  console.log(new_div_fr_answer_container_id)

  //new question text area
  var new_textarea_fr_create_question_textarea_id = document.createElement('textarea');
  new_textarea_fr_create_question_textarea_id.setAttribute('class' , 'create-question-textarea');
  new_textarea_fr_create_question_textarea_id.setAttribute('id' , 'create-question-textarea-id')
  new_textarea_fr_create_question_textarea_id.setAttribute('cols' , 50);
  new_textarea_fr_create_question_textarea_id.setAttribute('row' , 1);
  new_textarea_fr_create_question_textarea_id.style.fontSize = '20pt';

  //new for option text area wrrapeer 
  var new_option_text_area_wrapper = document.createElement('div');
  new_option_text_area_wrapper.setAttribute('class' , 'create-answer-textarea-container');
  new_option_text_area_wrapper.setAttribute('id' , new_splitted_cloned_container_id);

  var new_option_N_text_area_wrapper = document.createElement('div');
  new_option_N_text_area_wrapper.setAttribute('class' , 'create-answer-N-container');
  new_option_N_text_area_wrapper.setAttribute('id', new_id_spliited_lastChildContainer);

  var new_checkbox_inner = document.createElement('div');
  new_checkbox_inner.setAttribute('class' , 'create-qeuestion-radio-inner-circle');
  //create Element for checkBox outerCircle
  var new_checkbox = document.createElement('div');
  new_checkbox.setAttribute('class' , 'create-qeuestion-radio-outer-circle');
  //append innerCircle
  new_checkbox.appendChild(new_checkbox_inner);

  var new_answer = document.createElement('textarea');
  new_answer.setAttribute('name' , 'textareaopt');
  new_answer.setAttribute('id' , 'opt'+ (parseInt(lastChildString) + 1));
  new_answer.setAttribute('class' , 'create-answer-textarea');
  new_answer.setAttribute('placeholder' , 'opt'+ (parseInt(lastChildString) + 1))
  new_answer.style.fontSize = "14pt";

  new_option_N_text_area_wrapper.appendChild(new_checkbox);
  new_option_N_text_area_wrapper.appendChild(new_answer);
  new_option_text_area_wrapper.appendChild(new_option_N_text_area_wrapper);
  new_div_fr_answer_container_id.appendChild(new_textarea_fr_create_question_textarea_id);
  new_div_fr_answer_container_id.appendChild(new_option_text_area_wrapper);
  all_question_asnwer_container.appendChild(new_div_fr_answer_container_id);
}

所有这些都只是重复的方法。所以我的问题是,有没有更有效的方法来做到这一点,或者有没有像我可以用来使它更易于管理的类。

标签: javascripthtml

解决方案


您有多种选择,其中两种是:

  1. 如果您不介意每次都解析 HTML(并且在现代浏览器上解析 HTML非常快),您可以改用insertAdjacentHTML模板文字,这样您就可以轻松嵌入换行符并使用${x}嵌入值的语法:

    all_question_asnwer_container.insertAdjacentHTML("beforeend", `<div>
        (etc.)
    </div>`);
    
  2. 您可以根据需要template在 HTML 中使用克隆(通过cloneNode)的元素。这是链接页面中 MDN 示例的克隆部分

    var tbody = document.querySelector("tbody");
    var template = document.querySelector('#productrow'); // The template element
    
    // Clone the new row and insert it into the table
    var clone = template.content.cloneNode(true);
    var td = clone.querySelectorAll("td");
    td[0].textContent = "1235646565";
    td[1].textContent = "Stuff";
    
    tbody.appendChild(clone);
    

推荐阅读