TextArea 自己备份到它以前的值,例如

TextArea backup to it's previous value by itself, with example

由于 textarea 的奇怪行为,我几乎失去了理智,甚至很难复制一个演示,但幸运的是使用 outerHTML 属性 也会触发它。

在示例中:先单击更改,然后单击测试按钮,您将看到 textarea 恢复到其 原始值.如果你在点击测试之前检查它 dom 你会发现旧的 值持续存在 ,为什么会发生这种情况以及如何解决它? 谢谢。

function changevalue(){
 var text=document.getElementById("text");
  text.value="New Text";
}
function testing(){
 var text=document.getElementById("text");
  document.body.innerHTML+="<br>"+(text.outerHTML);
  document.body.innerHTML+="<br>"+(text.value); 
}  
<form name='test'>
<textarea id='text' name="content">Old Text</textarea>
</form>
<button onclick='changevalue()' >
change
</button>
<button onclick='testing()' >
test
</button>

我可以通过提供 .innerHTML 和 .value 来解决这个问题。相同的值。但是还有其他优雅的方式吗?

表单控件有一个 defaultValue property,这是它们在源 HTML 中指定的初始(默认)值。重置表单后,该值将始终恢复为 defualtValue

innerHTMLouterHTML 属性反映了 defaultValue,不是当前值(HTML fragment serialisation algorithm 中可能有一些内容覆盖了它)。

在下文中,您可以将文本区域的值更改为任何您喜欢的值,默认值将保持不变。

您可以更改 defaultValue,方法是为其分配一个新值。因此,如果您使用 outerHTML 复制表单控件并希望 defaultValue 与您正在复制的元素不同,您需要明确设置它。

cloneNode 方法(我认为这是比 outerHTML 更好的选择)具有相同的行为。

function showStuff(el) {
  let frag = document.createDocumentFragment();
  let span = document.createElement('span');
  let br = document.createElement('br');
  [['Value property: ', el.value],
   ['Value attribute: ', el.getAttribute('value')],
   ['Default value: ', el.defaultValue],
   ['outerHTML: ', el.outerHTML]
  ].forEach(props => {
    frag.appendChild(span.cloneNode()).textContent = props.join(' ');
    frag.appendChild(br.cloneNode());
  });
  let t = document.getElementById('elData');
  t.innerHTML = '';
  t.appendChild(frag);  
}
<form onsubmit="return false">
  <table>
    <tr>
      <td>Textarea
      <td><textarea name="ta0">Initial value</textarea>
    <tr>
      <td>Show props and atts
      <td><button onclick="showStuff(this.form.ta0)">Show stuff</button>
    <tr>
      <td id="elData" colspan="2">
    <tr>
      <td>Reset the form
      <td><input type="reset">
    <tr>
      <td>Set defaultValue<br>
          <input name="newValue0">
      <td><button onclick="this.form.ta0.defaultValue = this.form.newValue0.value">Change default value to this</button>
    <tr>
      <td>Set value via setAttribute(value)<br>
          <input name="newValue1">
      <td><button onclick="this.form.ta0.setAttribute('value', this.form.newValue1.value)">Change value attribute to this</button>

    <tr>
      <td>Clone textarea
      <td><button onclick="
        let ta1 = this.form.ta0.cloneNode(true);
        ta1.name = ta1.name + this.form.elements.length;
        form.appendChild(ta1);
      ">Clone text area</button>
  </table>
</form>

默认值

根据 HTML 规范,defualtValue must reflect the value content attribute。对于大多数表单控件,value 属性是显式的,例如<input value="foo">。但是,对于 textarea 元素,值内容属性由 HTML 中的初始值推断,例如<textarea>foo</textarea>.

DOM 值 属性 (input.value) 将反映控件的当前值,但是值属性 (input.getAttribute('value')) 将反映控件的值属性HTML(除非使用 setAttribute 更改)。

Textarea 元素在历史上没有值属性,因此虽然通过 get/setAttribute 支持它,但它本质上没有意义,因为它不用于任何事情(即 默认值)。设置它会导致它出现在 outerHTML 中,但它对 valuedefaultValue 没有影响 个属性。

序列化算法需要复制内容属性(即源 HTML 中或由 setAttribute 修改的内容属性),而不是 DOM 属性,因此两者不同之处在于内容属性用过的。例如。对于输入元素:

<input name="userID" value="1234">

通过 UI 或使用 DOM 值 属性(例如 form.userID = '5678')将值更改为什么并不重要,defaultValue 将保持为“1234”。这可以通过设置 defaultValue 属性 来改变,使用 setAttribute 不会改变它。

DOM 属性和 HTML 属性之间的断裂关系是历史性的,并且在很大程度上已得到修复,因此它们相互反映,但奇怪之处仍然存在。