【问题标题】:Javascript clone node is not copying all values from cloned to new objectJavascript克隆节点没有将所有值从克隆复制到新对象
【发布时间】:2017-07-08 06:14:06
【问题描述】:
<div class="container">
  <select class="btn" name="item">
    <option>Alpha</option>
    <option>Beta</option>
    <option>Gamma</option>
    <option>Theta</option>
  </select>
  <input type="text" class="desc" name="desc">
</div>

在本例中,“选择”下拉菜单中默认选择的元素是“Alpha”。我想克隆带有值的完整节点。如果我在下拉列表中选择不同的值并在输入框中输入一些文本,然后克隆节点,则只会克隆文本框值。新对象中“选择”下拉列表的值保持默认值 (Alpha)。

为什么“选择”和“输入”的克隆行为不同?

var parent = document.querySelector(".container");
var button = parent.querySelector(".btn");
var textbox = parent.querySelector(".desc");

  > textbox.value
  < "some random text"
  > button.value
  < "Gamma"

var cloned = parent.cloneNode(true);
var childButton = cloned.querySelector(".btn");
var childTextbox = cloned.querySelector(".desc");

  > childTextbox.value
  < "some random text"
  > childButton.value
  < "Alpha"

【问题讨论】:

  • @DeepakGang,有 3 个答案,你应该接受其中任何一个。
  • @Sagar V. 感谢您的提醒。发布问题后我去睡觉了。

标签: javascript select clone


【解决方案1】:

当您更改选择时,选择的状态将存储在浏览器中,克隆节点将永远不会包含浏览器更改和/或存储的对象/元素的状态。

但是对于input,它被存储为属性value的值并被克隆。

要克隆具有选定值的节点,

您应该检测到更改事件并向其添加selected 属性。

即为change事件添加select的事件监听器。

然后在回调函数中,通过使用将属性selected设置为该对象

selectElement.options[selectElement.selectedIndex].setAttribute("selected","");

运行下面的sn-p。

从列表中选择任何值并在文本框中键入内容并单击克隆按钮。

var parent = document.querySelector(".container");
var button = parent.querySelector(".btn");
var textbox = parent.querySelector(".desc");
console.log(button.value);
console.log(textbox.value);
function update(val){
  val.options[val.selectedIndex].setAttribute("selected","");
  
}


function clone(){
  var cloned = parent.cloneNode(true);
  document.querySelector(".container-2").appendChild(cloned);
  var childButton = cloned.querySelector(".btn");
  var childTextbox = cloned.querySelector(".desc");
  console.log(button.value);
  console.log(textbox.value);
}
<div class="container">
  <select class="btn" name="item" onchange="update(this);">
    <option>Alpha</option>
    <option>Beta</option>
    <option>Gamma</option>
    <option>Theta</option>
  </select>
  <input type="text" class="desc" name="desc">
</div>
<button onclick="clone();">Clone</button>
<div class="container-2"></div>

【讨论】:

  • But for input, it is stored as a value of the attribute value and get cloned. select 的 value 属性也会显示选中的值。有什么不同?
  • 只有存在selected 属性时才会保留选择属性的值。但在浏览器中,它被存储为状态。该属性不会自动添加到标签中。 @DeepakGarg
  • 谢谢!我会填塞它,但我仍然认为必须有更好的理由。想象一下被克隆的普通对象。期望新对象将是源的精确副本,但这里对象的一个​​属性(在对象中可见)没有被复制。
  • 这是一个很好的解决方案,但是如果您在克隆之前选择多个选项,多个选项标签上将具有 selected 属性。我通过遍历选项并在索引与 selectedIndex 不匹配时删除 selected 属性并在匹配时设置它来解决此问题。
  • @Peyman 是的,也发现了这个警告。实际上,这是该解决方案的一个主要缺陷,用户可以并且将选择一个选项然后选择另一个选项,在这种情况下会产生意想不到的结果。我刚刚添加了行 Array.from(el.options).forEach(option =&gt; option.removeAttribute('selected')); 以在设置所选选项之前重置所有选项。
【解决方案2】:

我使用 getElementsByClass() 方法来获取有趣的元素。然后通过 for 循环我添加一个 onchange 事件来克隆容器。注意在函数的末尾我将值 pf 父选择元素分配给克隆选择榆树。

var parent = document.getElementsByClassName("container");
var button = document.getElementsByClassName("btn");


for(var i=0;i<button.length;i++){
button[i].onchange=function(){  
var cloned = parent[0].cloneNode(true);  
 console.log(cloned);
 document.body.appendChild(cloned);
  cloned.childNodes[1].value=this.value;
};
}
<div class="container">
  <select class="btn" name="item">
    <option>Alpha</option>
    <option>Beta</option>
    <option>Gamma</option>
    <option>Theta</option>
  </select>
  <input type="text" class="desc" name="desc">
</div>

【讨论】:

  • 谢谢!但是,我一直在寻找围绕核心问题的解释。规范中一定有一些东西阻止了我丢失的值被克隆
【解决方案3】:

克隆&lt;select&gt; 不会复制&lt;option&gt;s 上的value= 属性。

发生这种情况是因为更改属性会更改表单控件的状态,但不会更改元素的 HTML selected 属性的值。
您可以在W3 specs 阅读更多相关信息。

在您的示例中,如果您检查 parent 节点的值,您将看到只有该元素具有正确的选定值,并且没有它的克隆。

【讨论】:

  • “表单控件的状态”和“HTML 选定属性的值”有什么区别?为什么这种推理只适用于下拉菜单而不适用于文本框?
  • @DeepakGarg 创建 2 个具有相同选项的“选择”下拉菜单,并在每个下拉菜单中选择不同的选项。现在从您的浏览器中检查他们的 HTML。你看有什么不同吗?答案是否定的,因为它们选择的值在其 HTML 中不可用,而是在内部存储在浏览器的特定选择下拉元素的状态中。
  • @user340674,我创建了 2 个“选择”下拉菜单,当检查时,我发现它们的值不同。 var button1 = parent.querySelector(".btn1"); var button2 = parent.querySelector(".btn2"); button1.value 是“Alpha”,而 button2.value 是“Gamma”(我在下拉菜单中选择了)。无论值没有被复制到新对象的原因是什么,我的问题是为什么该原因不适用于文本框?
  • @DeepakGarg 这不是检查,而是使用 javascript 来获取它们的值——我的意思是使用开发工具,并检查它们的 HTML。我不知道为什么它适用于输入而不适用于选择元素。
猜你喜欢
  • 1970-01-01
  • 2013-04-06
  • 2012-09-23
  • 1970-01-01
  • 2011-04-15
  • 2013-01-03
  • 2011-10-17
  • 1970-01-01
  • 2012-12-20
相关资源
最近更新 更多