window.HTMLTextAreaElement.prototype 与 textarea

问题描述 投票:0回答:1

谁能解释一下为什么下面的代码有效

const textarea = document.querySelector('textarea');
const submitButton = document.querySelector('button[aria-label="Submit"]');

const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
    window.HTMLTextAreaElement.prototype,
    'value'
  ).set;

const event = new Event('input', { bubbles: true });

function typeAndSubmit(text) {
  nativeInputValueSetter.call(textarea, text);
  textarea.dispatchEvent(event); 
  submitButton.click()
}

typeAndSubmit('Hello');

而且这个只是改变了textarea.value,但没有提交

const textarea = document.querySelector('textarea');
const submitButton = document.querySelector('button[aria-label="Submit"]');

const event = new Event('input', { bubbles: true });

function typeAndSubmit(text) {
  textarea.value = text
  textarea.dispatchEvent(event); 
  submitButton.click()
}

typeAndSubmit('Hello');

我用谷歌搜索了与 React 相关的类似问题。但它不是 React,它是纯 javascript 和 html。我不太明白为什么会发生这种情况))

javascript html
1个回答
0
投票

Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value')
提供
HTMLTextAreaElement
原型中存在的 getter 和 setter 函数。

两者都可以在

HTMLTextAreaElement
实例范围内作为函数调用。

getter 是一个只有一个参数(一个值)的函数。它是负责设置

HTMLTextAreaElement
实例值的函数。

所以:

Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value)
.set.call([HTMLTextArea instance], value);

(相当于

HTMLTextAreaElement.prototype.set.call(...)

相当于

someTextArea = 'value'

document.addEventListener(`click`, handle); 

// assign the HTMLTextAreaElement setter to a variable
// a bit less convoluted
const textSet = HTMLTextAreaElement.prototype.set;

function handle(evt) {
  if (evt.target.dataset.set) {
    console.clear();
    const textArea = document.querySelector(`textarea`);
    const text = evt.target.dataset.set;
    
    if (evt.target.useSet) {
      // call textSet for a HTMLTextAreaElement instance
      return textSet.call(textArea, text);
      //                  ^ instance
    }
    
    // use the HTMLTextAreaElement protoype setter
    return textArea.value = text;
  }
}
<textarea></textarea>
<p>
  call textSet to set to 
    <button data-use-set="1" 
      data-set="Hello world (call to textSet)"
      >'Hello world'</button>
  <br>
  use [textarea] =  to set to 
    <button data-set="Hello world (setter used)"
    >'Hello world'</button>
</p>

© www.soinside.com 2019 - 2024. All rights reserved.