65.9K
CodeProject 正在变化。 阅读更多。
Home

如何使用 React 和 ASP.Net Core 实现 CRUD 表单 - 第 3 部分

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.75/5 (7投票s)

2017 年 11 月 8 日

CPOL

8分钟阅读

viewsIcon

19225

在本教程的这一部分,我们将为我们高性能的 ASP.Net Core React.js 组件添加 CRUD(创建、读取、更新、删除)操作,而无需使用 Redux 或 JQuery。

引言

这是我们关于使用 ASP.NET Core 2.0 上的 React.js 构建 CRUD 表单的三部分系列文章的第二部分。 如果您还没有完成本教程的前两部分,请先完成它们,然后返回到此页面。

单击此处可阅读本教程的第二部分

第 2 部分:如何使用 React 和 ASP.Net Core 实现 CRUD 表单

操作链接

让我们开始在 Actor 组件的 Index 视图中添加操作链接。打开该文件(ClientApp/components/Actor/Index.tsx),并在 render() 方法中添加一个 HTML 按钮(如图 1 所示),该按钮将用于打开我们创建新记录的视图。

Index.tsx

图 1

为了实现所有 CRUD 操作,我们还需要用于读取详细信息、编辑(更新)和删除记录的按钮。向下滚动到 renderTable() 方法,并将下面显示的三个按钮插入到第一个 <td> </td> 标签之间(如图 2 所示)。

Index.tsx

图 2

我们需要 Javascript 处理程序来处理按钮将触发的操作。但在添加它们之前,我们需要在状态中添加标志,以指示是否应显示这些视图之一。我们还需要跟踪活动项的 id,因此我们为此添加了一个变量。滚动到 ActorState 接口,并按如下所示添加三个布尔标志以及 activeId 变量(如图 3 所示)。此外,在构造函数中初始化这些变量,将标志设置为 false,将 activeId 设置为 0(如图 3 所示)。

Index.tsx

图 3

现在我们可以添加 Javascript 处理程序,首先是 Create、Edit 和 Details。继续并将这三个处理程序复制到构造函数下方,如下所示(如图 4 所示)。

handleCreate() {
    this.setState({ showCreate: true, showDetails: false, showEdit: false })
}

handleEdit(id: number) {
	this.setState({ showEdit: true, showDetails: false, showCreate: false, activeId: id })
}

handleDetails(id: number) {
	this.setState({ showDetails: true, showCreate: false, showEdit: false, activeId: id})
}

图 4

最后但同样重要的是 Delete 处理程序。键入如下代码(如图 5 所示)。

handleDelete(id: number) {
    if (!confirm('Are you sure you want to delete this?'))
        return
	fetch('api/actor/delete/' + id, { method: 'delete' })
        .then(data => {
            this.setState(
                {
                    actor: this.state.actor.filter((rec) => {
						return (rec.Id != id);
                    })
                });
        });
}

图 5

我们需要为新视图添加 import 语句,以及一个用于 react-modal 的 import 语句,react-modal 是我们将用于显示其他视图的弹出组件(如图 5.1 所示)。

import * as Modal from 'react-modal'
import { CreateEdit } from './CreateEdit'
import { Details } from './Details'

图 5.1

我们需要稍微修改 render() 方法来渲染我们的新视图,这些视图将渲染在弹出窗口中。第一个方法 renderPopup() 仅检查我们的 showXXXXXX 标志以确定是否为给定视图显示弹出窗口。renderPopupContent() 方法顾名思义,渲染实际内容。让我们按如图所示键入这两个方法(如图 5.2 所示)。

renderPopup()

图 5.2

您可能已经注意到上一个代码中添加了一些新的 Javascript 处理程序。有一个用于关闭弹出窗口(closeModal()),另一个用于保存弹出窗口中的数据(handlePopupSave())。猜猜接下来是什么?您猜对了,我们得复制它们(如图 5.3 所示)!您问,为什么需要输入这么多?一位智者曾告诉我:“经验不是学习的最佳方式……它是唯一的方式。”

    closeModal() {
        this.setState({ showDetails: false, showCreate: false, showEdit: false });
    }
	
    handlePopupSave(success: boolean) {
        if (success)
            this.setState({ showCreate: false, showEdit: false });
    }

图 5.3

React-modal

React-modal 是我们用于显示其他视图的弹出组件。我们需要安装此组件才能使用它(这是显而易见的)。让我们使用 NPM 进行安装。

  1. 打开 Windows 资源管理器,如果您不使用 Windows,则打开文件资源管理器程序。
  2. 导航到项目的根文件夹(包含 bin\、Controllers\ 和 Views\ 文件夹的那个)。
  3. 键入以下命令(如图 5.4 所示)。
    npm install react-modal@2.3.2

npm

图 5.4

其他视图

如果感觉路途遥远,那确实如此。但我们快完成了。我们需要另外两个视图来处理其余的 CRUD 操作。具体来说,我们需要一个用于处理创建/编辑的视图,以及一个用于处理详细信息的视图。让我们从 Details 视图开始,因为它更简单。

Details 视图

右键单击 ClientApp/components/Actor 文件夹,然后选择 Add,然后选择 New Item...。在 Add New Item 弹出窗口的左侧,选择 ASP.Net Core,然后选择 Web,然后选择 Scripts。然后,就像我们在第 2 部分创建 Index 视图时一样,从中间框中选择 TypeScript JSX File。将新文件命名为:Details.tsx。

和以前一样,键入相同的 import 语句,并为 Details 状态创建一个接口,如下所示(如图 6 所示)。

import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import * as models from '../../models';

interface DetailsState {
    actor: models.Actor;
    loading: boolean;
}

interface DetailsProps {
	id: number
}    

图 6

与 Index 组件不同,我们将传递一个记录 id,因此我们需要为 Component Properties 创建一个接口。Component Properties 是您传递给 React 组件的值(此处为记录 ID)。如果您还没有这样做,请键入 DetailsProps 接口,如下所示(如图 6 所示)。

我们的 Details 组件类与我们为 Index 组件创建的组件非常相似。继续键入如下代码(如图 7 所示)。

Details.tsx

图 7

我们组件的最后一部分只是 renderDetails() 方法,它与 Index 组件中的方法相似,但要简单得多(如图 8 所示)。

renderDetails()

图 8

哇!如果您和我一样有同感。幸运的是,我们可以从这里看到隧道尽头的光明。让我们测试一下 Details 视图。由于我们还没有创建 CreateEdit 组件,因此需要注释掉三行代码。暂时注释掉 'import {CreateEdit}..' 行以及 renderPopupContent() 方法中的代码,如下所示(如图 9 和 10 所示)。

commented code

图 9

renderPopupContent()

图 10

现在我们可以运行应用程序并查看 Details 视图。只需单击任何 Details 链接即可触发弹出窗口。您可能会注意到对于大屏幕来说,定位不太合适。我们将在下一个 CSS 部分中解决这个问题。

Actor Details

图 11

注意:如果您无法运行应用程序,请不要担心,也绝对不要放弃。您可以在此处下载本教程的代码。

CreateEdit 视图

我们的最后一个 React 视图是 CreateEdit 视图。它将允许我们添加新记录以及编辑现有记录。在深入研究之前,请返回并取消注释我们上面为测试 Details 组件而注释掉的三行。继续...

在构建最后一个组件之前,让我们修复 Details 视图的定位问题。我们只需要添加一些 CSS... 展开 ClientApp/ 下的 css/ 文件夹,然后打开 site.css 文件。在 '@media (max-width: 767px)' 之前,粘贴以下 CSS(如图 11.1 所示),这将使弹出窗口向右偏移 25%(在导航菜单右侧)用于计算机屏幕,对于 837px 或更小的屏幕,则会填充大部分屏幕。

div.ReactModal__Content {
    left: 25% !important;
}

@media only screen and (max-width: 837px) {
    div.ReactModal__Content {
        top: 60px !important;
        left: 4% !important;
        right: 4% !important;
        bottom: 4% !important;
    }
}

图 11.1

让我们构建最后一个视图。到目前为止,您应该已经熟悉了这个过程。在 ClientApp/components/Actor 文件夹中创建一个新的 TypeScript JSX 文件,并将其命名为 CreateEdit.tsx。然后添加以下 import 语句(如图 12 所示)。

import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import './actor.css';
import {Actor} from '../../models'
import * as models from '../../models'

图 12

接下来,为组件的 State 和 Properties 创建接口(如图 13 所示)。

interface CreateEditState {
    actor: Actor;
    loading: boolean;
	save: boolean
}
interface CreateEditProps {
	id: number
    dbaction: string
    onSave?: any /* event*/
}

图 13

我们的组件类看起来与我们之前创建的两个组件相似(如图 14 所示)。我们需要向该类添加更多内容,因此请确保将其保持打开状态,即不要添加最后的花括号 }。

export class CreateEdit extends React.Component<createeditprops, createeditstate=""><CreateEditProps, CreateEditState> {
    constructor(props) {
        super(props);
        if (this.props.dbaction == "edit") {
			this.state = { actor: null, loading: true, save: false }
			fetch('api/actors/' + this.props.id, { method: 'get' })
                .then(response => response.json() as Promise<actor>)
                .then(data => {
                    this.setState({ actor: data, loading: false });
                });
        } else
			this.state = { actor: null, loading: false, save: false}
    }    
</actor></createeditprops,>

图 14

当添加新记录或修改现有记录时,我们需要将其保存到数据库。我们将按以下方式处理(如图 15 所示)。您可能会注意到我们将方法传递到 URL 中。这使我们能够使用一个表单来处理创建和编辑操作。

    handleSave(e) {
        e.preventDefault()
        let meth: string = (this.props.dbaction == "edit" ? "put" : "post")
        let form: Element = document.querySelector('#frmCreateEdit')
        let id = document.getElementById('Id') as HtmlInputElement
		fetch('api/actors/' + meth,
            {
                method: meth,
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(formToJson(form))
            })
<models.jsonresponse>            .then(data => {
				this.setState({ save: false, jsonResponse: data });
                this.props.onSave(true);
            });
    }
</models.jsonresponse>

图 15

我们的 render() 方法也应该很熟悉(如图 16 所示)。唯一的区别是我们在 'Edit Actor' 和 'Create Actor' 之间切换 <h1> 文本。

render()

图 16

我们的 renderForm() 方法渲染实际的 HTML 标记(如图 17 所示)。请注意,我们在输入中使用 defaultValue 属性以允许用户修改值。如果您设置 value 属性,React 将控制表单,并且不允许修改值。

renderForm()

图 17

最后但同样重要的是,我们需要一个实用程序来在提交时将表单序列化为 JSON。让我们键入以下代码,确保在组件类中添加最后的花括号 }(如图 18 所示)。

    /* utils*/
    isValidElement = element => {
        return element.name && element.value;
    };
    isValidValue = element => {
        return (['checkbox', 'radio'].indexOf(element.type) == -1 || element.checked);
    };
    formToJson = elements => [].reduce.call(elements, (data, element) => {
        console.log('formToJson()', element)
        if (this.isValidElement(element) && this.isValidValue(element)) {
            data[element.name] = element.value;
        }
        return data;
    }, {});    

图 18

这样就完成了我们的组件。如果行星对齐并且一切编译正确,您就可以运行您的 React 单页应用程序,并像原生应用程序一样无缝地执行所有 CRUD 操作!

Create Actor

图 18

Actor Details

图 19

Edit Actor

图 20

Delete Actor

图 21

好了!我们的其他两个组件:Movie 和 MovieActor 可以使用相同的方法构建,因此我们将留给读者自行探索。您可以在此处下载本教程的所有代码:here

最终想法

这是一段很长的旅程,您不这么认为吗?不过我必须承认一件事,那就是本教程中的所有代码都是使用 React Turbo Scaffolding 一键生成的,不到一分钟就完成了——是的,每一行,包括我们开始使用的服务器模型。只需指向我们的 Sql Server 数据库架构,我们就能一键生成整个应用程序——每个表(Actor、Movie 和 MovieActor)的每一行代码。事实上,React Turbo Scaffolding 还生成了:所有视图的自动分页、排序、表单验证和错误处理——这些功能在本教程中我们都删除了。而且,如果您在学习本教程的过程中,发现某些地方可以以略微不同的方式实现,React Turbo Scaffolding 提供了可修改的模板,允许您调整它生成的输出。  简而言之,它是一个“强大的工具”,可以让您和您的开发团队立即上手,并立即取得完整的结果——而不是三个月后。

了解更多 »

我们热爱 React。我们认为它比竞争对手更好。我们相信它有一个光明的未来,并且它的受欢迎程度只会增加,因为已经有数万名开发人员接受了它。祝您 React 开发顺利!

联系作者

历史

  • 2017年11月8日 首次发布

 

© . All rights reserved.