我创建了两个组件App
Inner
组件App组件包含一个表单。
我的内部组件包含一个常量数据,我进一步将其传递给危险的SetInnerHTML以设置内部html。 所以可以有任意数量的输入字段。有时它可以有 3 到 5 个输入字段。
在 React 中可能吗?如我所见,在这种情况下我不能进行双向绑定。
因为我相信这在 React 中是不可能的?
演示链接
export default function App() {
const handleSubmission = e => {
e.preventDefault();
};
return (
<div className="App">
<Inner />
<form onSubmit={handleSubmission}>
<div>Both two values comma separated: </div>
<button type="submit"> Submit </button>
</form>
</div>
);
}
const data = {
htmltag: `<html><style>table { font-family: arial, sans-serif; border-collapse: collapse; width: 40%;}td, th { border: 1px solid #dddddd; text-align: left; padding: 8px;}tr:nth-child(even) { background-color: #dddddd;}</style><body> <table> <tbody> <tr> <th>1</th> <th>2</th> </tr> <tr> <td>Hello</td> <td><input type = "text" /></td> </tr> <tr> <td>Welcome</td> <td><input type = "text" /></td> </tr> </tbody> </table> </body></html>`
};
export default function Inner() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<div dangerouslySetInnerHTML={{ __html: data.htmltag }} />
</div>
);
}
您将无法以 React 类型的方式访问此数据,但是您可以使用 React 支持的纯 JavaScript 访问这些数据。基本上,您不能将这些输入视为受控组件,而是将其视为不受控制的组件。
但是,这意味着您不会像使用受控组件那样实时获取状态更新,但您仍然可以访问数据。您只需在需要时(例如提交时(从 DOM 获取数据即可。
由于您也无法将 refs 直接传递给这些组件,因此您必须查询 DOM。您可以从容器的 ref(其内部 HTML 被危险设置的那个(开始,然后查询input
元素(和/或其他类似输入的元素(。
下面是一个示例:
应用.js
export default function App() {
const dataContainerRef = React.useRef(null);
const handleSubmission = e => {
e.preventDefault();
const inputs = Array.from(dataContainerRef.current.querySelectorAll("input"));
// if your inputs have unique names:
const formData = Object.fromEntries(inputs.map(input => [input.name, input.value]));
// or just get an array of the values:
const formDataArray = inputs.map(input => input.value);
};
return (
<div className="App">
<Inner dataContainerRef={ dataContainerRef } />
<form onSubmit={handleSubmission}>
<div>Both two values comma separated: </div>
<button type="submit"> Submit </button>
</form>
</div>
);
}
内.js
export default function Inner(props) {
const { dataContainerRef } = props;
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<div
ref={dataContainerRef}
className="data-container"
dangerouslySetInnerHTML={{ __html: data.htmltag }}
/>
</div>
);
}
这是一个代码沙盒演示。
请注意,如果您想了解使用纯JS获取表单数据的其他方法,则可以研究有关使用JS获取表单数据的问题(我建议不要将jQuery导入到React项目中(。
替代方法
如果您愿意更改数据的结构,使该data
不是 HTML 字符串,而是 JSON 格式,则可以自己动态创建input
元素并像往常一样控制它们。
例如,如果您像这样构建data
:
const data = {
inputNames: ["Hello", "Welcome"],
}
然后,您可以创建表单的formData
:
{
Hello: "",
Welcome: "",
}
它应该存储在Inner
的父级中,因为它拥有提交函数。
然后,您只需从data
初始化formData
,然后为每个给定inputName
动态创建一个input
元素。
以下是Inner
的示例:
export default function Inner(props) {
const { formData, setFormData } = props;
React.useEffect(() => {
// initialize `formData`
setFormData(
Object.fromEntries(data.inputNames.map(inputName => [inputName, ""]))
);
}, [setFormData]);
const inputRows = data.inputNames.map(inputName => (
<tr key={inputName}>
<td>{inputName}</td>
<td>
<input
name={inputName}
value={formData[inputName]}
onChange={event => {
event.persist();
setFormData(prev => ({
...prev,
[event.target.name]: event.target.value
}));
}}
/>
</td>
</tr>
));
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<table>
<tbody>{inputRows}</tbody>
</table>
</div>
);
}
这是一个演示。