TextArea выполняет резервное копирование на предыдущее значение, например - PullRequest
0 голосов
/ 21 марта 2020

Я почти сошел с ума из-за странного поведения textarea , его было даже сложно скопировать для демонстрации, но, к счастью, использование свойства outerHTML также вызывает его.

На примере: сначала нажмите на изменение, а затем на кнопку тестирования, вы увидите, что текстовая область вернулась к своему исходному значению . Если вы проверите его до нажатия кнопки «Тест», то обнаружите, что старое значение сохраняется , почему это происходит и как его решить? Спасибо.

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>

Я могу решить эту проблему, указав .inner HTML, а также .value. такое же значение. Но есть ли другой элегантный способ?

1 Ответ

1 голос
/ 21 марта 2020

Элементы управления формы имеют defaultValue свойство , которое является их начальным значением (по умолчанию), указанным в источнике HTML. Значение будет всегда возвращаться к defualtValue при сбросе формы.

внутренние HTML и внешние HTML свойства отражают defaultValue , а не текущее значение (вероятно, что-то есть в алгоритме сериализации фрагмента HTML , который его охватывает).

Далее вы можете изменить Значение текстовой области на любое значение, defaultValue останется прежним.

Вы можете изменить defaultValue , присвоив ему новое значение. Поэтому, если вы копируете элемент управления формы, используя external HTML и хотите, чтобы defaultValue отличался от копируемого элемента, вам необходимо явно установить его.

Метод cloneNode (который я считаю лучшим выбором, чем external HTML) имеет такое же поведение.

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>

defaultValue

Согласно HTML spe c, defualtValue должен отражать значение атрибута содержимого . Для большинства элементов управления формы атрибут value является явным, например <input value="foo">. Однако для элементов textarea атрибут содержимого значения выводится по начальному значению в HTML, например, <textarea>foo</textarea>.

Свойство значения DOM (input.value) будет отражать текущее значение элемента управления однако атрибут value (input.getAttribute('value')) будет отражать атрибут value в HTML (если только он не изменяется с помощью setAttribute ).

Элементы Textarea исторически не имели атрибута значения, поэтому, хотя они поддерживаются через get / setAttribute , они по сути бессмысленны, поскольку они ни для чего не используются (т. Е. Либо value * 1068) * или defaultValue ). При установке этого параметра он появляется в external HTML, но это не влияет на свойства value или defaultValue .

Алгоритм сериализации требует копирования атрибутов содержимого (то есть тех, которые находятся в источнике HTML или измененных с помощью setAttribute), а не свойств DOM, поэтому, когда они различаются, используется атрибут содержимого. Например, для элемента ввода:

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

не имеет значения, на что значение изменяется с помощью пользовательского интерфейса или с помощью свойства значения DOM (например, form.userID = '5678'), defaultValue останется как "1234". Это можно изменить, установив свойство defaultValue , используя setAttribute , которое не изменит его.

Разорванная связь между свойствами DOM и атрибутами HTML является историей c и в значительной степени исправлено так, что они отражают друг друга, но странности все еще остаются.

...