[英]Why is the value of a React controlled input element not being updated properly from a Chrome extension?
當我運行此代碼(它是 chrome 擴展的一部分)時,它應該只填寫特定網站的#username
和#password
輸入的信息,在這種情況下為https://wordplay.com/login 。
但是,輸入元素的值並沒有真正改變。 從視覺上看,輸入字段中有文本,但是當我檢查元素並查看 value 屬性時,它仍然是空白的。 直到我手動在框中鍵入一些內容。 如果我在輸入中輸入一些東西,那么值會更新得很好。
此外,當我嘗試提交表單時,它們都變回空。
const username = document.getElementById('username');
username.value = request.username;
const password = document.getElementById('password');
password.value = request.password;
這可能與該站點使用的任何框架有關。
在這種情況下, https ://wordplay.com/login 使用 React 並且這些字段是受控制的輸入,因此該表單上的邏輯不依賴於輸入的 DOM 值,而是依賴於 React 狀態中的值。 從文檔:
在 HTML 中,諸如
<input>
、<textarea>
和<select>
類的表單元素通常會維護自己的狀態並根據用戶輸入進行更新。 在 React 中,可變狀態通常保存在組件的 state 屬性中,並且僅使用setState()
更新。我們可以通過使 React 狀態成為“單一事實來源”來將兩者結合起來。 然后呈現表單的 React 組件還控制后續用戶輸入時該表單中發生的事情。 以這種方式由 React 控制其值的輸入表單元素稱為“受控組件”。
因此,最簡單的方法可能是關注輸入,然后使用Document.execCommand()
:
const username = document.getElementById('username'); const password = document.getElementById('password'); username.focus(); document.execCommand('insertText', false, 'Alice'); password.focus(); document.execCommand('insertText', false, 'password');
<input id="username" /> <input id="password" />
否則,您可以嘗試在更改它們的值后使用這些字段中的Event() 構造函數手動調度change
、 input
和/或blur
事件。 在這種情況下,只有input
有效。
另外,請注意Event()
的第二個可選參數包含一個字段bubbles
,默認情況下為false
。 你需要那個是true
。 否則,這將不起作用,因為 React 正在偵聽document
上的事件。
此外,您可能還需要使用Element.setAttribute()
,因為這將更新 DOM 上的value
屬性(字段上的初始值),而element.value
將更新當前值(以及顯示值)。 但是,在這種情況下,不需要它。 有關更多信息,請參閱HTML 中的屬性和屬性有什么區別? .
這種方法可能有一些時間問題,您可能需要在更新多個輸入時使用setTimeout
來處理,所以如果第一個有效,我會改用那個。
const username = document.getElementById('username'); // This updates the value displayed on the input, but not the DOM (you can do that with setAttribute, // but it's not needed here): username.value = 'Bob'; // Dispatch an "input" event. In some cases, "change" would also work: username.dispatchEvent(new Event('input', { bubbles: true })); // It looks like only one field will be updated if both events are dispatched // straight away, so you could use a setTimeout here: setTimeout(() => { const password = document.getElementById('password'); password.value = 'password'; password.dispatchEvent(new Event('input', { bubbles: true })); });
<input id="username" /> <input id="password" />
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.