DMOZ中文网站分类目录-免费收录各类优秀网站的中文网站目录.
  • DmozDir.org
DMOZ目录快速登录入口-免费收录各类优秀网站的中文网站目录.由人工编辑,并提供网站分类目录检索及地区分类目录检索,是站长免费推广网站的有力平台!

如何创建一个电子商务网站与之反应

  • 如何创建一个电子商务网站与之反应

  • 已被浏览: 77 次2020年10月14日    来源:  DMOZ中文网站分类目录
  • 戴文创建了一个基本的电子商务网站与反应,利用反应状态管理背景,并添加用于处理身份验证和车管理的基本方法。

    在本教程中,我们将看看如何建立与反应的非常简单的电子商务Web应用程序。它不会成为下一个Shopify,但希望它会成为一种有趣的方式来演示如何适合REACT为建设充满活力和迷人的用户界面。

    该应用程序将展示一个基本的购物车管理系统,以及处理用户身份验证的简单方法。我们将充分利用上下文做出反应,以替代状态管理框架如终极版或MobX的,我们将创建一个使用JSON-server软件包假的后端。

    下面是什么,我们会建设一个截图:

    The finished app

    此应用程序的代码可以在GitHub上。

    先决条件

    本教程假设你有JavaScript的基础知识和反应。如果你是新的反应,你可能想看看我们的初学者指南。

    要构建应用程序,您的PC上安装节点需要一个新的版本。如果不是这种情况,那么头部到节点的主页,并下载正确的系统的二进制文件。或者,你可以考虑使用版本管理器安装节点。我们对在这里使用版本管理的教程。

    节点捆绑了故宫,对JavaScript的软件包管理器,与我们要安装一些我们将使用的库。您可以了解更多关于此使用NPM。

    您可以检查这两个都正确安装通过发出命令行下面的命令:

    <预的tabindex = “0” 类= “语言的bash ”> <代码类=“ bash的语言的bash”>节点-v

    > 12.18.4

    NPM -v

    > 6.14.8

    做完这些后,让我们创建一个新的开始作出反应工程与创建阵营应用程序的工具。您可以安装这种全球范围内,或使用<代码> NPX ,像这样:

    <预的tabindex =“0”类=“语言的bash‘> <代码类=’bash的语言的bash”> NPX创建反应的应用内的电子商务

    当这个已经完成,变更到新创建的目录:

    <预的tabindex = “0” 类= “语言的bash ”> <代码类=“ bash的语言的bash”> CD电子商务

    在这个应用中,我们将使用作出反应的路由器来处理路由。要安装该模块,运行:

    <预的tabindex = “0” 类= “语言的bash ”> <代码类=“ bash的语言的bash”> NPM安装反应路由器-DOM

    我们还需要JSON-服务器和JSON-服务器身份验证来创建我们的假后端处理身份验证:

    <预的tabindex = “0” 类= “语言的bash ”> <代码类=“ bash的语言的bash”> NPM安装JSON-服务器JSON-服务器-AUTH

    我们需要Axios公司制作Ajax请求我们的假后端。

    <预的tabindex = “0” 类= “语言的bash ”> <代码类=“ bash的语言的bash”> NPM安装Axios公司

    而我们需要JWT解码,使我们可以分析JWT我们的后端将响应:

    <预的tabindex = “0” 类= “语言的bash ”> <代码类=“ bash的语言的bash”> NPM安装JWT解码

    最后,我们将使用布尔玛CSS框架样式此应用程序。要安装此,运行以下命令:

    <预的tabindex = “0” 类= “语言的bash ”> <代码类=“ bash的语言的bash”> NPM安装布尔玛

    入门

    首先,我们需要将样式表添加到我们的应用程序。为了实现这一目标,我们将添加一个import语句包含在 index.js 文件这个文件中的<代码>的src 的文件夹中。这将应用样式表跨应用程序中所有的组件:

    <预的tabindex = “0” 类= “语言的javascript ”> <代码类=“ JavaScript语言的JavaScript”>导入 “布尔玛/ CSS / bulma.css”;

    上下文设置

    正如前面提到的,我们将使用阵营在我们的应用程序上下文。这是一种较新的加成反应并提供了一种通过组件树数据,而不必在每一级通过手动向下道具。

    如果您想了解有关在使用上下文复习阵营申请,看看我们的教程“如何更换终极版与之反应钩和上下文API”。

    在复杂的应用中,其中需要上下文通常是必要的,也可以是多个上下文中,每个都具有其自己的数据以及与所述一组部件的需要的数据和方法的方法。例如,可以有一个<代码> ProductContext 用于处理在使用与产品相关的数据的部件,而另一个<代码> ProfileContext 用于处理与认证和用户数据的数据。然而,让事情尽可能简单起见,我们将只使用一个上下文实例。

    为了创建的背景下,我们创建了一个<代码> Context.js 文件和<代码> withContext.js 在我们的应用程序的文件的src 的目录:

    <预的tabindex = “0” 类= “语言的bash ”> <代码类=“ bash的语言的bash”> CD SRC

    触摸Context.js withContext.js

    然后下面添加到<代码> Context.js

    <预的tabindex = “0” 类= “语言的javascript ”> <代码类=“ JavaScript语言的JavaScript”>进口从 “反应” 反应;

    常量上下文= React.createContext({});

    出口默认的上下文;

    这创建上下文和上下文数据初始化为一个空对象。接下来,我们需要创建一个部件的包装材料,这是我们将使用包使用的上下文数据和方法的组件: <代码类=’JSX语言JSX “> // SRC / withContext.js

    进口从“反应”反应;

    从“./Context”导入语境;

    常量withContext = WrappedComponent => {

    常量WithHOC =道具=> {

    回报(

    {上下文=> }

    );

    };

    返回WithHOC;

    };

    出口默认withContext;

    这可能看起来复杂一点,但本质上它是所有做一个高阶组件,其中追加了上下文包裹组件的道具。

    它分解一点,我们可以看到,在 withContext 功能作为它的参数阵营组件。然后,它返回一个函数,组件的道具作为参数。内返回的函数,我们包裹在我们的上下文中的组件,则分配给它的上下文为道具:<代码>上下文= {上下文} 。在 {...道具} 位保证了部件保持被传递给它在第一位置的任何道具。

    所有这意味着,我们可以按照我们整个应用这种模式:

    <预的tabindex = “0” 类= “语言JSX ”> <代码类=“ JSX语言JSX”>进口从 “反应” 反应;

    进口withContext从 “../withContext”;

    常量车=道具=> {

    //我们现在可以访问上下文为props.context

    };

    出口默认withContext(车);

    脚手架在应用软件

    现在,让我们来创建我们需要为我们的应用程序的基本导航功能的正常组件的镂空版本。这些都是<代码> AddProducts ,<代码>车,<代码>登录和<代码>产品,我们打算将它们放置在一个<代码>部件的<代码的目录内> SRC 目录中:

    <预的tabindex = “0” 类= “语言的bash ”> <代码类=“ bash的语言的bash”> MKDIR部件

    CD组件

    触摸AddProduct.js Cart.js Login.js ProductList.js

    在<代码> AddProduct.js 添加:

    <预的tabindex = “0” 类= “语言JSX ”> <代码类=“ JSX语言JSX”>进口从 “反应” 反应;

    出口默认功能addProduct命令(){

    返回<> addProduct命令

    }

    在<代码> Cart.js 添加:

    <预的tabindex = “0” 类= “语言JSX ”> <代码类=“ JSX语言JSX”>进口从 “反应” 反应;

    出口默认功能车(){

    返回<>车

    }

    在<代码> Login.js 添加:

    <预的tabindex = “0” 类= “语言JSX ”> <代码类=“ JSX语言JSX”>进口从 “反应” 反应;

    出口默认功能登录(){

    返回<>登录

    }

    最后,在<代码> ProductList.js 添加:

    <预的tabindex = “0” 类= “语言JSX ”> <代码类=“ JSX语言JSX”>进口从 “反应” 反应;

    出口默认功能产品列表(){

    返回<>产品

    }

    接下来,我们需要建立了<代码> App.js 文件。在这里,我们将处理应用程序的导航以及定义它的数据和方法来管理它。

    首先,我们建立了导航的。变化<代码> App.js 如下:

    <预的tabindex = “0” 类= “语言JSX ”> <代码类=“ JSX语言JSX”>导入反应,{元器件}从 “反应”;

    进口{交换机,路由链路,如BrowserRouter路由器}从 “反应路由器-DOM”;

    进口addProduct命令从 "./components/AddProduct";

    从“./components/Cart”进口车;

    进口登录从” ./components/Login";

    进口产品列表从“./components/ProductList”;

    从“./Context”导入语境;

    出口默认类应用程序扩展组件{

    构造(道具){

    超级(道具);

    this.state = {

    用户:空,

    购物车:{},

    产品:[]

    };

    this.routerRef = React.createRef();

    }

    渲染(){

    回报(

    值= {{

    ... this.state,

    removeFromCart:this.removeFromCart,

    addToCart:this.addToCart,

    登录:this.login,

    addProduct命令:this.addProduct,

    clearCart:this.clearCart,

    结帐:this.checkout

    }}

    >

    <路由器REF = {this.routerRef}>

    类名=“导航栏容器”

    角色=“导航”

    咏叹调标签=“主导航”

    >

    电子商务

    <标签

    角色=“按钮”

    类=“导航栏-汉堡汉堡”

    ARIA标签=“菜单”

    ARIA-扩大= “假”

    数据目标=“navbarBasicExample”

    的onClick = {E => {

    e.preventDefault();

    this.setState({showMenu:this.state.showMenu!});

    }}

    >

    <跨度咏叹调隐藏=“真”>

    <跨度咏叹调隐藏=“真”>

    <跨度咏叹调隐藏=“真”>

    this.state.showMenu? “活跃” : ””

    }`}>

    <链接=“/产品”的className =“导航栏项目”>

    制品

    {this.state.user && this.state.user.accessLevel <1 &&(<链接= “/添加产品” 的className = “导航栏项目”>

    添加产品

    )}

    <链接=“/购物车”的className =“导航栏项目”>

    大车

    类名=“标签是原色”

    风格= {{marginLeft: “5px的”}}

    >

    {Object.keys(this.state.cart)。长度}

    {!this.state.user? (

    <链接=“/登录”的className =“导航栏项目”>

    登录

    ):(

    <链接= “/” 的onClick = {this.logout}的className = “导航栏项目”>

    登出

    )}

    <开关>

    <路线确切路径= “/” 成分= {}产品列表/>

    <路线确切路径= “/登录” 成分= {}登录/>

    <路线确切路径= “/购物车” 成分= {}车/>

    <路线确切路径= “/添加副产物” 组分= {} addProduct命令/>

    <路线确切路径= “/产品” 成分= {}产品列表/>

    );

    }

    }

    我们的<代码>应用组件将负责初始化应用程序和数据也将定义的方法来操作该数据。首先,我们定义使用 Context.Provider 组件的上下文数据和方法。的数据和方法作为属性,<代码>值被传递,在<代码>提供商组件来替换所述上下文创建给定的对象。 (请注意,该值可以是任何数据类型。)我们通过状态值和一些方法,我们将很快确定。

    接下来,我们建立我们的应用程序导航。为了实现这一点,我们需要包装我们的应用程序以<代码>路由器组分,其可以是<代码> BrowserRouter (如在我们的情况下)或<代码> HashRouter 。接下来,我们定义使用切换和<代码>路线的部件我们的应用程序的途径。我们还创建应用程序的导航菜单,在使用<代码>每个链路在所提供的链接组分反应路由器模块。我们还添加一个引用,<代码> routerRef 到<代码>路由器组件,以使我们的<代码>内从访问路由器应用组件。

    为了测试这一点,头到项目根目录(例如,<代码> /文件/吉姆/桌面/电子商务),并启动创建使用<代码> NPM启动阵营应用开发服务器。一旦已经启动,默认浏览器应该打开,你会看到我们的应用程序的骨架。请务必按一下周围,并确保所有的导航作品。

    纺纱了一个假的后端

    在下一步,我们将建立一个假的后端存储产品和处理用户身份验证。如前所述,为此,我们将使用JSON-服务器上创建一个假的REST API和JSON-服务器身份验证,以一个简单的基于JWT的认证流程添加到我们的应用程序。

    JSON-服务器的工作方式是,它在从文件系统并使用它来创建一个内存数据库与相应的端点与它交互的JSON文件读取。现在,让我们创建的JSON文件。在项目的路线,创建一个新的后台的文件夹,该文件夹中创建一个新的 db.json 文件:

    <预的tabindex = “0” 类= “语言的bash ”> <代码类=“ bash的语言的bash”> MKDIR后端

    CD后端

    触摸db.json

    打开<代码> db.json 并添加以下内容:

    <预的tabindex = “0” 类= “语言的javascript ”> <代码类=“ JavaScript语言的JavaScript”> {

    “用户”:

    {

    “电子邮件”:“regular@example.com”

    “密码”: “$ 2A $ 10 $ 2myKMolZJoH.q.cyXClQXufY1Mc7ETKdSaQQCC6Fgtbe0DCXRBELG”

    “ID”:1

    },

    {

    “电子邮件”:“admin@example.com”

    “密码”: “$ 2A $ 10 $ w8qB40MdYkMs3dgGGf0Pu.xxVOOzWdZ5 / Nrkleo3Gqc88PF / OQhOG”

    “ID”:2

    }

    ]

    “产品”:[

    {

    “ID”: “hdmdu0t80yjkfqselfc”

    “名”:“鞋子”,

    “股票”:10,

    “价格”:399.99,

    “shortDesc”: “法无facilisi Curabitur在拉克丝交流velit ornare lobortis。”

    “描述”: “CRAS sagittis Praesent NEC nisl一个普鲁斯blandit灵猫UT LEO Donec华富蚤,ultricies NEC,pellentesque欧盟的Pretium QUIS,SEM Fusce一个智能资料。。。”

    },

    {

    “ID”: “3dc7fiyzlfmkfqseqam”

    “名”:“包装袋”,

    “股票”:20,

    “价格”:299.99,

    “shortDesc”: “法无facilisi Curabitur在拉克丝交流velit ornare lobortis。”

    “描述”: “CRAS sagittis Praesent NEC nisl一个普鲁斯blandit灵猫UT LEO Donec华富蚤,ultricies NEC,pellentesque欧盟的Pretium QUIS,SEM Fusce一个智能资料。。。”

    },

    {

    “ID”: “aoe8wvdxvrkfqsew67”

    “名”:“衬衫”,

    “股票”:15,

    “价格”:149.99,

    “shortDesc”: “法无facilisi Curabitur在拉克丝交流velit ornare lobortis。”

    “描述”: “CRAS sagittis Praesent NEC nisl一个普鲁斯blandit灵猫UT LEO Donec华富蚤,ultricies NEC,pellentesque欧盟的Pretium QUIS,SEM Fusce一个智能资料。。。”

    },

    {

    “ID”: “bmfrurdkswtkfqsf15j”

    “名”:“短裤”,

    “股票”:5,

    “价格”:109.99,

    “shortDesc”: “法无facilisi Curabitur在拉克丝交流velit ornare lobortis。”

    “描述”: “CRAS sagittis Praesent NEC nisl一个普鲁斯blandit灵猫UT LEO Donec华富蚤,ultricies NEC,pellentesque欧盟的Pretium QUIS,SEM Fusce一个智能资料。。。”

    }

    ]

    }

    我们在这里创造两种资源 - <代码>用户和<代码>产品。综观<代码>用户的资源,你会发现,每个用户都有一个ID,一个电子邮件地址和密码。因为它的使用bcryptjs加密的密码显示为杂乱的字母和数字。您不存储密码在你的应用程序的纯文本的任何地方是很重要的。

    这就是说,每个密码的纯文本版本简直是“密码” - 不带引号。

    现在,从项目的根目录发出以下命令启动服务器:

    <预的tabindex = “0” 类= “语言的bash ”> <代码类=“ bash的语言的bash”> ./ node_modules /的.bin / JSON-服务器-AUTH ./backend/db.json --port 3001

    这将启动上<代码> HTTP JSON-服务器://本地主机:3001 。多亏了JSON-服务器身份验证的中间件,在用户的资源也会给我们的 /登录的端点,我们可以在应用程序中使用,以模拟记录。

    让我们尝试一下使用https://hoppscotch.io。打开一个新的窗口链接,然后改变的方法来<代码> POST 和URL为的http://本地主机:3001 /登录。接下来,确保原始输入开关设置为并输入以下内容作为原始请求主体:

    <预的tabindex = “0” 类= “语言的javascript ”> <代码类=“ JavaScript语言的JavaScript”> {

    “电子邮件”:“regular@example.com”

    “密码”:“密码”

    }

    点击发送,你应该接受(进一步下跌的页面)的响应,看起来像这样:

    <预的tabindex = “0” 类= “语言的javascript ”> <代码类=“ JavaScript语言的JavaScript”> {

    “的accessToken”: “eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InJlZ3VsYXJAZXhhbXBsZS5jb20iLCJpYXQiOjE2MDE1Mzk3NzEsImV4cCI6MTYwMTU0MzM3MSwic3ViIjoiMSJ9.RAFUYXxG2Z8W8zv5-4OHun8CmCKqi7IYqYAc4R7STBM”

    }

    这是一个JSON网络令牌,有效期为一个小时。在具有适当的后端的正常应用,您需要把它保存在客户端,然后将其发送到服务器,只要你的要求受保护的资源。该服务器将验证它接收的令牌,如果一切手续办妥后,它会与你请求的数据作出反应。

    这一点是值得重复。您需要验证您的服务器上的受保护资源的请求。这是因为代码,在客户端运行可能被逆向工程和篡改。

    下面是对Hoppscotch成品请求的链接。你只需要按下发送。

    如果您想了解更多关于使用Node.js的使用JSON网络令牌,请咨询我们的教程。

    实施身份验证的应用程序做出反应

    在本节我们将需要在我们的应用程序中的爱可信和jwt_decode包。进口添加到<代码> App.js 文件的顶部:

    <预的tabindex = “0” 类= “语言的javascript ”> <代码类=“ JavaScript语言的JavaScript”>从 "Axios公司" 进口Axios公司;

    从“JWT解码”进口jwt_decode;

    如果你看看在类的顶部,你会看到我们已经宣布在状态的用户。这是最初设置为null。

    接下来,我们需要确保用户在加载时的应用程序通过设置组件的用户安装启动,如下图所示。这种方法添加到<代码>应用组件,如果存在的话,其载荷从本地存储器的状态的最后一个用户会话:

    <预的tabindex = “0” 类= “语言的javascript ”> <代码类=“ JavaScript语言的JavaScript”> componentDidMount(){

    让用户= localStorage.getItem( “用??户”);

    用户=用户? JSON.parse(用户):空;

    this.setState({用户});

    }

    接下来,我们定义<代码>登录注销方法,其被附加到上下文:

    <预的tabindex = “0” 类= “语言的javascript ”> <代码类=“ JavaScript语言的JavaScript”>登录名=异步(电子邮件,密码)=> {

    常量解析度= AWAIT axios.post(

    的 "http://本地主机:3001 /登录",

    {电子邮件,密码},

    ).catch((RES)=> {

    返回{状态:401,消息: "未经授权"}

    })

    如果(res.status === 200){

    常量{电子邮件} = jwt_decode(res.data.accessToken)

    常量用户= {

    电子邮件,

    令牌:res.data.accessToken,

    ACCESSLEVEL:电子邮件=== "admin@example.com"? 0:1

    }

    this.setState({用户});

    localStorage.setItem( “用??户”,JSON.stringify(用户));

    返回true;

    }其他{

    返回false;

    }

    }

    注销= E => {

    e.preventDefault();

    this.setState({用户:空});

    localStorage.removeItem( “用??户”);

    };

    登录方法,使一个Ajax请求我们的 /登录的终点,传递给它的任何输入到登录表单(其中我们就会在一分钟)的用户。如果从端点的响应有一个200个状态码,我们可以假设用户的凭据是正确的。然后,我们在解码服务器的响应,以获得用户的电子邮件的令牌中发送,保存电子邮件,令牌和状态的用户的访问级别之前。如果一切顺利的话,该方法返回的真正,否则<代码>假。我们可以在我们的使用该值登录的成分是什么决定display.Note,对于访问级别的检查是在这里很肤浅的一个,它不会是困难的登录,普通用户用户使自己的管理员。然而,对于保护资源假设请求发送响应之前在服务器上验证,用户将不能够做的比看到一个额外的按钮等等。服务器验证将确保他们将无法得到任何保护的数据。

    如果你想实现一个更强大的解决方案,你可以做第二次请求当用户登录时,或当应用程序加载,以获得当前用户的权限。这是不幸的是超出这个教程的范围。

    注销方法清除从两个状态和本地存储的用户。

    创建登录组件

    接下来,我们可以处理<代码>登录组件。该组件可以使用上下文数据。为它能够访问这些数据和方法,它具有使用我们先前创建withContext 方法包裹。

    ALTER <代码>的src / Login.js 像这样:

    <预的tabindex = “0” 类= “语言JSX ”> <代码类=“ JSX语言JSX”>导入反应,{元器件}从 “反应”;

    进口{重定向}从 “反应路由器-DOM”;

    进口withContext从 “../withContext”;

    一流的登录扩展组件{

    构造(道具){

    超级(道具);

    this.state = {

    用户名: ””,

    密码:“”

    };

    }

    handleChange = E => this.setState({[e.target.name]:e.target.value,错误: “”});

    登录名=(E)=> {

    e.preventDefault();

    常量{用户名,密码} = this.state;

    如果(!用户名||密码){

    返回this.setState({错误: “填写所有内容”});

    }

    this.props.context.login(用户名,密码)

    。然后((的loggedIn)=> {

    如果(!的loggedIn){

    this.setState({错误: “无效Credentails”});

    }

    })

    };

    渲染(){

    回报!this.props.context.user? (

    <>

    登录



    <形式的onSubmit = {this.login}>

    <标签的className = “标签”>电子邮件:

    <输入

    类名=“输入”

    键入=“电子邮件”

    名称=“用户名”

    的onChange = {this.handleChange}

    />

    <标签的className = “标签”>密码:

    <输入

    类名=“输入”

    类型=“密码”

    NAME = “密码”

    的onChange = {this.handleChange}

    />

    {this.state.error &&(

    {this.state.error}

    )}

    <按钮

    类名= “按钮是伯被概述的IS-拉右”

    >

    提交

    ):(

    <重定向到= “/产品”/>

    );

    }

    }

    出口默认withContext(登录);

    此组件呈现与两个输入的形式来收集用户的登录凭证。在提交,该组件调用<代码>登录方法,该方法是通过上下文传递。该模块还可以确保重定向到产品页面,如果用户已经登录。

    如果你现在去到http://本地主机:3000 /登录,您应该能够登录与任何上述名称/密码的连击。

    创建产品视图

    现在,我们需要从我们的后端部分产品获取到显示在我们的应用程序。我们能够做到这一点的组件安装在应用的组成部分,因为我们做了登录的用户:

    <预的tabindex = “0” 类= “语言的javascript ”> <代码类=“ JavaScript语言的JavaScript”>异步componentDidMount(){

    The login page with an email and password field

    让用户= localStorage.getItem( “用??户”);

    常量的产品= AWAIT axios.get(的 "http://本地主机:3001 /产品");

    用户=用户? JSON.parse(用户):空;

    this.setState({用户,产品:products.data});

    }

    在上面的代码片段中,我们已标记在 componentDidMount 生命周期钩为异步,这意味着我们可以提出一个要求我们的<代码> /产品端点,然后等待数据坚持入状态之前归还。

    接下来,我们可以创建产品页面,这也将作为应用程序登陆页面。该页面将利用两个部分组成。第一个是<代码> ProductList.js ,这将显示在页面体,而另一个是在list.Alter <代码> ProductItem.js 组件,用于每个产品的<代码>产品列表组件,如下图所示:

    <预的tabindex = “0” 类= “语言JSX ”> <代码类=“ JSX语言JSX”>进口从 “反应” 反应;

    进口ProductItem从 “./ProductItem”;

    进口withContext从 “../withContext”;

    常量产品列表=道具=> {

    常量{产品} = props.context;

    回报(

    <>

    我们的产品


    {产品&& products.length? (

    products.map((产品,指数)=>(

    产物= {}产品

    关键= {}索引

    addToCart = {props.context.addToCart}

    />

    ))

    ):(

    <跨度的className =“标题具有文本灰度光”>

    没有产品找到了!

    )}

    );

    };

    出口默认withContext(产品列表);

    因为该列表是依赖于数据中的情况下,我们用<代码> withContext 函数包裹它。此组件使用 ProductItem 的组件,其中我们还没有创建呈现产品。它也传送一个<代码> addToCart从上下文方法(其中我们也没有限定)到 ProductItem 。这消除了需要将工作与在 ProductItem 组件上下文直接。

    现在,让我们创建<代码> ProductItem 的组件:

    <预的tabindex = “0” 类= “语言的bash ”> <代码类=“ bash的语言的bash”> CD SRC /组件

    触摸ProductItem.js

    并添加以下内容:

    <预的tabindex = “0” 类= “语言JSX ”> <代码类=“ JSX语言JSX”>进口从 “反应” 反应;

    常量ProductItem =道具=> {

    常量{产物} =道具;

    回报(

    <图中的className = “图像是-64×64”>

    SRC = “https://bulma.io/images/placeholders/128x128.png”

    ALT = {product.shortDesc}

    />

    {产品名称}{” ”}

    <跨度的className = “标签是原色”> $ {product.price}

    {product.shortDesc}

    {product.stock> 0? (

    <小> {product.stock + “可用”}

    ):(

    <小的className = “具有文本-危险”>缺货

    )}

    <按钮

    类名= “按钮是小的概述的IS-初级IS-拉右”

    的onClick = {()=>

    props.addToCart({

    ID:product.name,

    产品,

    量:1

    })

    }

    >

    添加到购物车

    );

    };

    出口默认ProductItem;

    此元素显示卡上的产品,还提供了动作按钮将产品添加到用户的购物车。

    添加产品

    现在,我们有一些在我们的商店展示,让我们创建的管理员用户增加新产品的接口。首先,让我们定义添加的产品的方法。我们要做的是,在<代码>应用组件,如下图所示:

    <预的tabindex = “0” 类= “语言的javascript ”> <代码类=“ JavaScript语言的JavaScript”> addProduct命令=(产品,回调)=> {

    让产品= this.state.products.slice();

    Products

    products.push(产品);

    this.setState({产品},()=>回调&&回调());

    };

    此方法接收<代码>产品对象,并将其追加到产品的阵列,然后将其保存到该应用状态。它也将收到回调函数,在成功添加产品执行。

    现在,我们可以继续填写<代码> addProduct命令组件:

    <预的tabindex = “0” 类= “语言JSX ”> <代码类=“ JSX语言JSX”>导入反应,{元器件}从 “反应”;

    进口withContext从 “../withContext”;

    进口{重定向}从 “反应路由器-DOM”;

    从“爱可信”进口爱可信;

    常量INITSTATE = {

    名称: ””,

    价钱: ””,

    股票: ””,

    shortDesc: “”,

    说明:“”

    };

    类addProduct命令延伸元器件{

    构造(道具){

    超级(道具);

    this.state = INITSTATE;

    }

    节省=异步(E)=> {

    e.preventDefault();

    常量{名称,价格,库存,shortDesc介绍} = this.state;

    如果(名称&&价格){

    常量ID =的Math.random()的toString(36).substring(2)+ Date.now()的toString(36)。。

    的await axios.post(

    的“http://本地主机:3001 /产品的,

    {ID,名称,价格,库存,shortDesc,说明},

    this.props.context.addProduct(

    {

    名称,

    价格,shortDesc,

    描述,

    股票:股票|| 0

    },

    ()=> this.setState(INITSTATE)

    );

    this.setState(

    {闪存:{状态:“是 - 成功”,味精:“产品已成功创建”}}

    );

    }其他{

    this.setState(

    {闪存:{状态:“是-危险”,味精:“请输入名称和价格”}}

    );

    }

    };

    handleChange = E => this.setState({[e.target.name]:e.target.value,错误: “”});

    渲染(){

    常量{名称,价格,库存,shortDesc介绍} = this.state;

    常量{用户} = this.props.context;

    回报!(用户&& user.accessLevel <1)? (

    <重定向到= “/”/>

    ):(

    <>

    添加产品



    <形式的onSubmit = {this.save}>

    <标签的className = “标签”>产品名称:

    <输入

    类名=“输入”

    类型=“文本”

    NAME = “名”

    值= {名称}

    的onChange = {this.handleChange}

    需要

    />

    <标签的className = “标签”>价格:

    <输入

    类名=“输入”

    类型=“号码”

    NAME = “价”

    值= {}价格

    的onChange = {this.handleChange}

    需要

    />

    <标签的className = “标签”>可用库存:

    <输入

    类名=“输入”

    类型=“号码”

    NAME = “股票”

    值= {}股票

    的onChange = {this.handleChange}

    />

    <标签的className = “标签”>简要说明:

    <输入

    类名=“输入”

    类型=“文本”

    NAME = “shortDesc”

    值= {shortDesc}

    的onChange = {this.handleChange}

    />

    <标签的className = “标签”>说明

    类名= “textarea的”

    类型=“文本”

    行= “2”

    风格= {{调整大小: “无”}}

    名称=“描述”

    值= {}描述

    的onChange = {this.handleChange}

    />

    {this.state.flash &&(

    {} this.state.flash.msg

    )}

    <按钮

    类名= “按钮是伯被概述的IS-拉右”

    类型=“提交”

    的onClick = {this.save}

    >

    提交

    );

    }

    }

    出口默认withContext(addProduct命令);

    这部分做了一些事情。它检查是否有存储于上下文,并且如果该用户的当前用户具有<代码> ACCESSLEVEL 小于1(即,如果它们是管理员)。如果是这样,它呈现的形式来添加一个新的产品。如果不是,它重定向到应用程序的主页。

    再次,请注意,这种检查可以很容易地在客户端上绕过。在现实世界的应用,您需要在服务器上执行额外的检查,以确保允许用户创建新的产品。

    假设形式呈现,有几个字段为用户填写(其<代码>名称的是强制性的)。不管用户输入在组件的状态跟踪。当提交表单时,该组件的保存方法被调用,这使得Ajax请求到我们的后端来创建一个新的产品。我们也创造一个独特的ID(其中JSON-服务器要求),并通过沿了。造成这种情况的代码来自堆栈溢出的线程。

    最后,我们调用<代码> addProduct命令我们通过下收到的方法,新创建的产品添加到我们的全局状态和复位形式。假设所有的这是成功的,我们设置在状态的<代码>闪属性,然后将更新的界面,以通知产物创建的用户。

    如果<代码>名称或<代码>价格字段缺失,我们设置了<代码>闪存属性告知该用户。

    花一秒钟来检查你的进步。以管理员身份登录(电子邮件:<代码> admin@example.com ,密码:<密码>密码),并确保您在导航看到Add按钮的产品。导航到该页面,然后使用表单创建两个新产品。最后,回到主界面,并确保新产品都出现在产品列表中了。

    加入购物车管理

    现在,我们可以添加和展示产品,做的最后一件事是实现我们的车管理。我们已经初始化,我们的车在<代码> App.js 的,但我们还需要确保我们从组件加载本地存储加载现有车空的对象。

    更新<代码> componentDidMount 方法在<代码> App.js 如下:

    <预的tabindex = “0” 类= “语言的javascript ”> <代码类=“ JavaScript语言的JavaScript”>异步componentDidMount(){

    Add product page

    让用户= localStorage.getItem( “用??户”);

    让车= localStorage.getItem( “购物车”);

    常量的产品= AWAIT axios.get(的 "http://本地主机:3001 /产品");用户=用户? JSON.parse(用户):空;

    车=车? JSON.parse(购物车):{};

    this.setState({用户,产品:products.data,购物车});

    }

    接下来,我们需要定义车函数(也<代码> App.js )。首先,我们将创建的 addToCart 方法:

    <预的tabindex = “0” 类= “语言的javascript ”> <代码类=“ JavaScript语言的JavaScript”> addToCart = cartItem => {

    让车= this.state.cart;

    如果(购物[cartItem.id]){

    车[cartItem.id] .amount + = cartItem.amount;

    }其他{

    购物[cartItem.id] = cartItem;

    }

    如果(购物[cartItem.id] .amount>车[cartItem.id] .product.stock){

    车[cartItem.id] .amount =购物[cartItem.id] .product.stock;

    }

    localStorage.setItem( “购物车”,JSON.stringify(购物车));

    this.setState({车});

    };

    此方法使用附加的项目ID作为车对象关键的项目。我们使用的对象,而不是车的阵列,以使易数据检索。此方法检查车的对象,看是否与该键的项目存在。如果是这样,它增加量;否则它会创建一个新的条目。第二个<代码>如果语句确保用户不能添加更多的项目比实际可用。然后,该方法节约了推车的状态,这被传递到通过上下文的应用程序的其他部分。最后,该方法保存更新的车以提供持久的本地存储。

    接下来,我们将定义<代码> removeFromCart 方法从用户购物车中删除特定的产品和 clearCart 于来自用户购物车中删除所有产品:

    <预的tabindex = “0” 类= “语言的javascript ”> <代码类=“ JavaScript语言的JavaScript”> removeFromCart = cartItemId => {

    让车= this.state.cart;

    删除车[cartItemId];

    localStorage.setItem( “购物车”,JSON.stringify(购物车));

    this.setState({车});

    };

    clearCart =()=> {

    让车= {};

    localStorage.removeItem( “购物车”);

    this.setState({车});

    };

    removeCart 方法删除使用所提供的产品密钥的产物。然后相应地更新应用程序状态和本地存储。在 clearCart 方法重置车在状态一个空对象并移除在本地存储器上的车条目。

    现在,我们可以继续使车的用户界面。类似的产品列表中,我们实现这一点使用两个元素:第一,<代码> Cart.js ,这使得页面布局,以及使用所述第二组分的购物项目的列表,<代码> CartItem。 JS

    <预的tabindex = “0” 类= “语言JSX ”> <代码类=“ JSX语言JSX”> // ./src/components/Cart.js

    进口从“反应”反应;

    进口withContext从 “../withContext”;

    进口CartItem从 “./CartItem”;

    常量车=道具=> {

    The cart

    const的{}购物= props.context;

    常量cartKeys = Object.keys(购物车|| {});

    回报(

    <>

    我的车


    {cartKeys.length? (

    {cartKeys.map(密钥=>(

    cartKey = {}键

    关键= {}键

    cartItem = {车[键]}

    removeFromCart = {props.context.removeFromCart}

    />

    ))}


    <按钮

    的onClick = {props.context.clearCart}

    类名=“按钮是预警”

    >

    清空购物车

    {”“}

    <按钮

    类名=“按钮是-成功”

    的onClick = {props.context.checkout}

    >

    退房

    ):(

    在车没有产品!

    )}

    );

    };

    出口默认withContext(车);

    组件也通过从上下文到 CartItem 的方法。在通过上下文车对象值,并返回一个<代码> CartItem 的每一个的阵列部件循环。它还提供了一个按钮,清除用户购物车。

    接下来是<代码> CartItem 组件,这是非常像<代码> ProductItem 组件,但几微妙的变化:

    让我们先来创建组件:

    <预的tabindex = “0” 类= “语言的bash ”> <代码类=“ bash的语言的bash”> CD SRC /组件

    触摸CartItem.js

    然后添加以下内容:

    <预的tabindex = “0” 类= “语言JSX ”> <代码类=“ JSX语言JSX”>进口从 “反应” 反应;

    常量CartItem =道具=> {

    常量{cartItem,cartKey} =道具;

    常量{产物,量} = cartItem;

    回报(

    <图中的className = “图像是-64×64”>

    SRC = “https://bulma.io/images/placeholders/128x128.png”

    ALT = {product.shortDesc} />

    {产品名称}{” ”}

    <跨度的className = “标签是原色”> $ {product.price}

    {product.shortDesc}

    <小> {`$ {量}在cart`}

    的className =“媒体的权利”

    的onClick = {()=> props.removeFromCart(cartKey)}

    >

    <跨度的className = “删除是-大”>

    );

    };

    出口默认CartItem;

    该组件显示了产品信息和选择项目的数量。它还提供了一个按钮,从购物车中删除产品。

    最后,我们需要添加结帐方法在应用组件:

    <预的tabindex = “0” 类= “语言的javascript ”> <代码类=“ JavaScript语言的JavaScript”>结帐=()=> {

    如果(!this.state.user){

    this.routerRef.current.history.push( “/登录”);

    返回;

    }

    常量购物= this.state.cart;

    常量的产品= this.state.products.map(p值=> {

    如果(购物[p.name]){

    p.stock = p.stock - 购物[p.name] .amount;

    axios.put(

    `HTTP://本地主机:3001 /产品/ $ {p.id}`

    {。P},

    }

    返回磷;

    });

    this.setState({产品});

    this.clearCart();

    };

    该方法进行检查以查看用户正在在前进之前登录。如果用户没有登录,则用户重定向到使用我们附接到<代码>路由器组件更早路由器参考登录页面。

    通常情况下,在正规电子商务网站,这是在结算过程会发生,但我们的应用程序,我们就假设用户已经支付,因此从可用项目的列表中删除他们购买的物品。我们也将使用Axios公司来更新我们的后端的库存水平。

    有了这个,我们已经成功地完成了我们的基本的购物车。

    结论

    在本教程中,我们使用反应脚手架出一个基本的购物车的界面。我们使用上下文多个组件和JSON-服务器之间移动数据和方法,坚持数据。我们还使用JSON-服务器授权来实现基本的认证流程。

    这个应用程序是绝不是一个成品,并可能在许多方面得到改善。举例来说,下一步将是添加适当的后端有一个数据库,并进行服务器上进行验证检查。你也可以给管理员用户的能力,编辑和删除产品。

    我希望你喜欢这个教程。请不要忘记,这个应用程序的代码可以在GitHub上。

    想要潜入更多反应是?退房阵营的设计模式和最佳实践和大量的相互反应在SitePoint顶级资源。

    Products
    以上信息来源于网络,如有侵权,请联系站长删除。

    TAG:电子商务 创建 反应 站点

  • 上一篇:如何为您的移动网站创建一个QR码阅读器
  • 与“如何创建一个电子商务网站与之反应”相关的资讯
  • 为电子商务创建的数字助理适应每个商店的需求
  • 在德克萨斯州的立场:Swat命令领导者死亡,枪手的站点后4名受伤
  • 12提示创建一个引人注目的YouTube通道拖车(+示例)
  • 研究人员创建了一种确切地知道它的相机
  • 如何为商业社交饲料创建一个主题 - 数字营销博客