Reactjs 在接口和类中多次指定相同声明的概念是什么?
我正在努力学习用typescript处理表单,并从中做出反应。第一次做出明确的反应 下面是Reactjs 在接口和类中多次指定相同声明的概念是什么?,reactjs,typescript,Reactjs,Typescript,我正在努力学习用typescript处理表单,并从中做出反应。第一次做出明确的反应 下面是Form.tsx import * as React from "react"; interface IFormProps { /* The http path that the form will be posted to */ action: string; } export interface IValues { /* Key value pairs for all the field
Form.tsx
import * as React from "react";
interface IFormProps {
/* The http path that the form will be posted to */
action: string;
}
export interface IValues {
/* Key value pairs for all the field values with key being the field name */
[key: string]: any;
}
export interface IErrors {
/* The validation error messages for each field (key is the field name */
[key: string]: string;
}
export interface IFormState {
/* The field values */
values: IValues;
/* The field validation error messages */
errors: IErrors;
/* Whether the form has been successfully submitted */
submitSuccess?: boolean;
}
export class Form extends React.Component<IFormProps, IFormState> {
constructor(props: IFormProps) {
super(props);
const errors: IErrors = {};
const values: IValues = {};
this.state = {
errors,
values
};
}
/**
* Returns whether there are any errors in the errors object that is passed in
* @param {IErrors} errors - The field errors
*/
private haveErrors(errors: IErrors) {
let haveError: boolean = false;
Object.keys(errors).map((key: string) => {
if (errors[key].length > 0) {
haveError = true;
}
});
return haveError;
}
/**
* Handles form submission
* @param {React.FormEvent<HTMLFormElement>} e - The form event
*/
private handleSubmit = async (
e: React.FormEvent<HTMLFormElement>
): Promise<void> => {
e.preventDefault();
if (this.validateForm()) {
const submitSuccess: boolean = await this.submitForm();
this.setState({ submitSuccess });
}
};
/**
* Executes the validation rules for all the fields on the form and sets the error state
* @returns {boolean} - Whether the form is valid or not
*/
private validateForm(): boolean {
// TODO - validate form
return true;
}
/**
* Submits the form to the http api
* @returns {boolean} - Whether the form submission was successful or not
*/
private async submitForm(): Promise<boolean> {
// TODO - submit the form
return true;
}
public render() {
const { submitSuccess, errors } = this.state;
return (
<form onSubmit={this.handleSubmit} noValidate={true}>
<div className="container">
{/* TODO - render fields */}
<div className="form-group">
<button
type="submit"
className="btn btn-primary"
disabled={this.haveErrors(errors)}
>
Submit
</button>
</div>
{submitSuccess && (
<div className="alert alert-info" role="alert">
The form was successfully submitted!
</div>
)}
{submitSuccess === false &&
!this.haveErrors(errors) && (
<div className="alert alert-danger" role="alert">
Sorry, an unexpected error has occurred
</div>
)}
{submitSuccess === false &&
this.haveErrors(errors) && (
<div className="alert alert-danger" role="alert">
Sorry, the form is invalid. Please review, adjust and try again
</div>
)}
</div>
</form>
);
}
}
import*as React from“React”;
界面道具{
/*表单将发布到的http路径*/
动作:字符串;
}
导出接口IValues{
/*键为字段名的所有字段值的键值对*/
[键:字符串]:任意;
}
导出接口错误{
/*每个字段的验证错误消息(键是字段名*/
[键:字符串]:字符串;
}
导出接口状态{
/*字段值*/
价值观:价值观;
/*字段验证错误消息*/
错误:错误;
/*表单是否已成功提交*/
submitSuccess?:布尔值;
}
导出类表单扩展了React.Component{
构造器(道具:道具){
超级(道具);
常量错误:IErrors={};
常量值:IValues={};
此.state={
错误,
价值观
};
}
/**
*返回传入的errors对象中是否存在任何错误
*@param{IErrors}errors-字段错误
*/
私有haveErrors(错误:IErrors){
设haveError:boolean=false;
Object.keys(errors).map((key:string)=>{
如果(错误[key]。长度>0){
haveError=true;
}
});
返回错误;
}
/**
*处理表格提交
*@param{React.FormEvent}e-表单事件
*/
私有handleSubmit=async(
e:React.FormEvent
):承诺=>{
e、 预防默认值();
if(this.validateForm()){
const submitSuccess:boolean=wait this.submitForm();
this.setState({submitSuccess});
}
};
/**
*执行表单上所有字段的验证规则并设置错误状态
*@返回{boolean}-表单是否有效
*/
私有validateForm():布尔值{
//TODO-验证表单
返回true;
}
/**
*将表单提交到http api
*@returns{boolean}-表单提交是否成功
*/
专用异步submitForm():承诺{
//待办事项-提交表格
返回true;
}
公共渲染(){
const{submitSuccess,errors}=this.state;
返回(
{/*TODO-呈现字段*/}
提交
{提交成功&&(
表单已成功提交!
)}
{submitSuccess===false&&
!this.haveErrors(errors)&(
很抱歉,发生了意外错误
)}
{submitSuccess===false&&
这个.有错误(errors),(
抱歉,表单无效。请检查、调整并重试
)}
);
}
}
我不理解的是,类表单的构造函数具有
错误
值
它们都可以作为简单的对象数组来处理,但为什么会有这么多声明呢?正如我所看到的:
IValues
IErrors
代表他们
我寻求帮助来理解所有这些额外声明背后的概念。当您写入接口时,您就同意了一个契约:接口的形式在编译时保证是数据的形式
当你传递裸数据结构时,你没有这样的保证:你得到的数据可能比你想象的要多或少,唯一的验证方法是运行时检查。这些检查比编译时检查更昂贵
它们都可以作为简单的对象数组来处理
处理事情的方法不止一种,而这篇文章的作者已经决定用下面的方法来处理事情。这是否是处理事情的最佳方法取决于你自己。我只能解释它们背后的原因
export interface IValues {
/* Key value pairs for all the field values with key being the field name */
[key: string]: any;
}
export interface IErrors {
/* The validation error messages for each field (key is the field name */
[key: string]: string;
}
第一个接口(IValues
)声明了一个契约,其中任何实现它的对象都必须包含与任何类型的值耦合的字符串键
第二个接口(IErrors
)指定一个协定,其中任何实现它的对象都必须包含指向字符串值的字符串键
这是键值对的概念,也称为哈希、字典或映射,具体取决于您所熟悉的语言
Typescript实际上有一个名为Record
的内置类型,它允许您执行上述操作,而不会过于冗长
type Record<K extends keyof any, T> = { [P in K]: T }
当遇到第一个错误时,此检查可以短路以返回true。顺便说一句,它只检查至少一个单数形式的错误,因此最好将其命名为hasrerror
或hasrerrors
private hasError(errors: IErrors) {
for (let [key, value] of Object.entries(errors))
if (value) // <---- if (value) alone is enough as an empty string '' is falsy
return true;
return false;
}
为什么?submitSuccess
定义为布尔值,无需将其设置为false
谢谢你,但我无法联系。你能给我举个例子吗?这样我就可以连接我的神经网络了……对不起,我的无知:(它们都可以作为简单的对象数组来处理:当然,但是您可能会遇到运行时错误或奇怪的行为,因为代码期望它们是对象,而不是数组。指定类型正好可以避免此类错误:如果您尝试使用数组初始化它们,则会出现编译时错误。如果商店只接受Visa卡,如果他们在支付页面上清楚地告诉你这一点,对你来说更容易,而不是让你尝试使用万事达卡并得到难以诊断的错误。这里也一样:界面避免出错。我相信界面
更为人所知
private haveErrors(errors: IErrors) {
let haveError: boolean = false;
Object.keys(errors).map((key: string) => {
if (errors[key].length > 0) {
haveError = true;
}
});
return haveError;
}
private hasError(errors: IErrors) {
for (let [key, value] of Object.entries(errors))
if (value) // <---- if (value) alone is enough as an empty string '' is falsy
return true;
return false;
}
{submitSuccess === false && ...} = {!submitSuccess && ...}