【问题标题】:Why my input's value get cleared when I append a child?当我追加一个孩子时,为什么我的输入值会被清除?
【发布时间】:2015-12-29 01:53:13
【问题描述】:

当我在 div 中附加一个元素时遇到问题,我输入的所有值(包括选定的选项)都会被清除,如下所示:

正如您所看到的,当我单击“Añadir tecla”按钮时,文本框中的文本和所选选项“Shift”会返回到默认选项“Flechas de movimiento”。

为什么会发生这种情况,我该如何避免?

我的代码是下一个:

var controls = [{value: "flechas", text: "Flechas de movimiento"}, {value: "letras", text: "Letras (WASD)"}, {value: "enter", text: "Enter"}, {value: "control", text: "Ctrl"}, {value: "alt", text: "Alt"}, {value: "espacio", text: "Espacio"}, {value: "der", text: "Click derecho"}, {value: "izq", text: "Click izquierdo"}, {value: "mover", text: "Mover el ratón"}, {value: "shift", text: "Shift"}, {value: "customkey", text: "Especificar tecla"}];

function addControl(e) 
{
    e.appendChild(getControlSelect());
}

function getControlSelect() 
{
    var select = document.createElement('select'),
        option,
        i = 0,
        il = controls.length,
        html = document.createElement('div'),
        text = document.createElement('input'),
        delbtn = document.createElement('input');

    text.type = "text";

    delbtn.type = "button";
    delbtn.value = "-";

    for (; i < il; ++i)
    {
        option = document.createElement('option');
        option.setAttribute('value', controls[i].value);
        option.appendChild(document.createTextNode(controls[i].text));
        select.appendChild(option);
    }
    html.innerHTML += "<b>Tecla</b><br>";
    html.appendChild(select);
    html.innerHTML += "<br><b>Acción</b><br>";
    html.appendChild(text);
    html.appendChild(delbtn);

    return html;
}

HTML 代码:

<div>
    <input type="button" value="Añadir tecla" onclick="addControl(this.parentNode)" />
</div>

如您所见,当我单击“Añadir tecla”时,我调用 addControl 函数,并将 parentNode 作为唯一参数(稍后将用于在其中附加子节点)。

所以,我不知道问题出在哪里,我认为一切都是正确的,但它需要一些东西来避免值被清除。

编辑:我分享的代码没有问题,但我的完整代码在这里:

var controls = [{value: "flechas", text: "Flechas de movimiento"}, {value: "letras", text: "Letras (WASD)"}, {value: "enter", text: "Enter"}, {value: "control", text: "Ctrl"}, {value: "alt", text: "Alt"}, {value: "espacio", text: "Espacio"}, {value: "der", text: "Click derecho"}, {value: "izq", text: "Click izquierdo"}, {value: "mover", text: "Mover el ratón"}, {value: "shift", text: "Shift"}, {value: "customkey", text: "Especificar tecla"}],
	skippedIndexes = [],
	sep = "<div class='sep' id='firstsep' style='width: 200px;'></div>",
	oldIndex = 0;//,
	//sInd = 0;

function addControl(e) 
{

	if(e.lastChild.className != "sep") e.innerHTML += sep;
	e.appendChild(getControlSelect());
	e.innerHTML += sep.replace(" id='firstsep'", "");
}

function onSelectChange(e) 
{
	//Modify the array
	//a = e.associatedInput

	//console.log(e.dataset.i);

	/*var newIndex;

	newIndex = e.selectedIndex;

	if(skippedIndexes.length > 0 && skippedIndexes.indexOf(oldIndex) > -1) skippedIndexes.splice(skippedIndexes.indexOf(oldIndex), 1); //Delete oldIndex

	if(skippedIndexes.length > 0 && skippedIndexes.indexOf(newIndex) == -1) skippedIndexes.push(newIndex);

	oldIndex = newIndex;*/

	//Change associated



}

function deleteFirstSep() 
{
	if(!document.getElementById("firstsep").nextSibling) document.getElementById("firstsep").remove();
}

function getControlSelect() 
{
	var select = document.createElement('select'),
	    option,
	    i = 0,
	    il = controls.length,
	    html = document.createElement('div'),
	    text = document.createElement('input'),
	    delbtn = document.createElement('input'),
	    ascinpt = document.createElement('input'),
	    html1 = document.createElement('div');

	html1.style.display = "inline-block";

	text.type = "text";
	text.name = "accion[]";
	text.style.width = "158px";

	delbtn.type = "button";
	delbtn.setAttribute('onclick', 'var e = this.parentNode;e.nextSibling.remove();e.remove();deleteFirstSep();');
	delbtn.value = "-";
	delbtn.style.padding = "0 5px";
	delbtn.style.marginLeft = "5px";
	delbtn.style.position = "relative";
	delbtn.style.top = "-20px";
	delbtn.style.left = "2px";

	ascinpt.name = "tecla[]";
	ascinpt.type = "hidden";

	select.id = "htmlkey";
	select.dataset.associatedInput = ascinpt;
	//select.dataset.i = sInd;
	//sInd++;
	select.setAttribute("onchange", "onSelectChange(this)");

	for (; i < il; ++i)
		if(skippedIndexes.indexOf(i) == -1) 
		{
		    option = document.createElement('option');
		    option.setAttribute('value', controls[i].value);
		    option.appendChild(document.createTextNode(controls[i].text));
		    select.appendChild(option);
		}
	html1.innerHTML += "<b>Tecla</b><br>";
	html1.appendChild(select);
	html1.innerHTML += "<br><b>Acción</b><br>";
	html1.appendChild(text);
	html.appendChild(html1);
	html.appendChild(delbtn);

	return html;
}
.sep {
  border-top: 4px dashed #A4A4A4;
  margin: 15px 0 15px 0;
}
<div>
    <input type="button" value="Añadir tecla" onclick="addControl(this.parentNode)" />
</div>

【问题讨论】:

  • 您的代码对我来说运行得很好,当我单击按钮时,没有输入会丢失它们的值。您确定没有其他可能影响此的 javascript 事件触发吗?
  • 好的。我忘了说我有select.setAttribute("onchange", "onSelectChange(this)");。因此,当我更改值时,我调用了一个空函数,但是,删除此代码行会发生同样的事情。也许是浏览器?我正在使用 Chrome 46。
  • 对我来说也很好用。
  • 您是否尝试过刷新浏览器或清除缓存?您提供的缓存内容可能仍在加载您删除的代码。
  • 发生这种情况是因为您正在重写容器元素的 html。这样,现场财产就会丢失。您应该在内存中创建一个元素并附加它,而不是重写实际的 html 属性。

标签: javascript html dom input


【解决方案1】:

问题是你覆盖了 HTML 代码

element.innerHTML += newHTML;

这摆脱了当前元素的状态,包括事件侦听器、输入值、检查等。

您应该使用appendChildinsertAdjacentHTML

element.insertAdjacentHTML('beforeend', newHTML);

var controls = [{value: "flechas", text: "Flechas de movimiento"}, {value: "letras", text: "Letras (WASD)"}, {value: "enter", text: "Enter"}, {value: "control", text: "Ctrl"}, {value: "alt", text: "Alt"}, {value: "espacio", text: "Espacio"}, {value: "der", text: "Click derecho"}, {value: "izq", text: "Click izquierdo"}, {value: "mover", text: "Mover el ratón"}, {value: "shift", text: "Shift"}, {value: "customkey", text: "Especificar tecla"}],
  skippedIndexes = [],
  sep = "<div class='sep' id='firstsep' style='width: 200px;'></div>",
  oldIndex = 0; //,
//sInd = 0;

function addControl(e) {

  if (e.lastChild.className != "sep") e.innerHTML += sep;
  e.appendChild(getControlSelect());
  e.insertAdjacentHTML('beforeend', sep.replace(" id='firstsep'", ""));
}

function onSelectChange(e) {}

function deleteFirstSep() {
  if (!document.getElementById("firstsep").nextSibling) document.getElementById("firstsep").remove();
}

function getControlSelect() {
  var select = document.createElement('select'),
    option,
    i = 0,
    il = controls.length,
    html = document.createElement('div'),
    text = document.createElement('input'),
    delbtn = document.createElement('input'),
    ascinpt = document.createElement('input'),
    html1 = document.createElement('div');

  html1.style.display = "inline-block";

  text.type = "text";
  text.name = "accion[]";
  text.style.width = "158px";

  delbtn.type = "button";
  delbtn.setAttribute('onclick', 'var e = this.parentNode;e.nextSibling.remove();e.remove();deleteFirstSep();');
  delbtn.value = "-";
  delbtn.style.padding = "0 5px";
  delbtn.style.marginLeft = "5px";
  delbtn.style.position = "relative";
  delbtn.style.top = "-20px";
  delbtn.style.left = "2px";

  ascinpt.name = "tecla[]";
  ascinpt.type = "hidden";

  select.id = "htmlkey";
  select.dataset.associatedInput = ascinpt;
  //select.dataset.i = sInd;
  //sInd++;
  select.setAttribute("onchange", "onSelectChange(this)");
  for (; i < il; ++i)
    if (skippedIndexes.indexOf(i) == -1) {
      option = document.createElement('option');
      option.setAttribute('value', controls[i].value);
      option.appendChild(document.createTextNode(controls[i].text));
      select.appendChild(option);
    }
  html1.insertAdjacentHTML('beforeend', "<b>Tecla</b><br>");
  html1.appendChild(select);
  html1.insertAdjacentHTML('beforeend', "<br><b>Acción</b><br>");
  html1.appendChild(text);
  html.appendChild(html1);

  html.appendChild(delbtn);
  return html;
}
.sep {
  border-top: 4px dashed #A4A4A4;
  margin: 15px 0 15px 0;
}
<div>
  <input type="button" value="Añadir tecla" onclick="addControl(this.parentNode)" />
</div>

【讨论】:

  • 感谢您的建议!您能否提供一些改进我的代码组织的更多提示?
  • @Ikillnukes 与其从头开始重建新控件,不如考虑使用cloneNode 克隆现有控件。避免使用内联样式,而是添加一个类并在样式表中定义它们。避免需要全局函数的事件处理程序内容属性,使用事件处理程序 IDL 属性或事件侦听器。您可以将代码发布到codereview.stackexchange.com 以获得更多建议。
猜你喜欢
  • 2013-01-08
  • 1970-01-01
  • 2022-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-04
  • 2021-04-16
  • 1970-01-01
相关资源
最近更新 更多