react基础06--react综合案例-电商网站导航

2023-11-09

1 介绍

继上文 react基础05–react-router 路由, 本文将根据上述01-05小节的基础知识实现一个小型电商网站的基础导航和搜索模型.
分类导航是一个很重要且常见的功能, 常见美团App商品 菜品都是一级导航, 京东、淘宝等商城多为二级甚至三级导航。本文将实现一个基础的商品导航功能, 具体包括一级二级导航、商品展示、查看详情、筛选、搜索 等功能。

2 案例设计模块

2.1 分类导航数据模型设计

结构设计:
电商网站-{电器、服装、玩具、手机}
电器-{冰箱、洗衣机、空调}
服装-{外套、衬衣、裤子}
玩具-{挖掘机、赛车、游戏机}
手机-{华为、小米、苹果}

数据设计(data.json):

{
    "navs": [
        {
            "id": 1,
            "pid": 0,
            "name": "电器"
        }, 
        {
            "id": 2,
            "pid": 1,
            "name": "冰箱"
        }, 
        {
            "id": 3,
            "pid": 0,
            "name": "空调"
        },        
        {
            "id": 4,
            "pid": 0,
            "name": "服装"
        }, 
        {
            "id": 5,
            "pid": 6,
            "name": "外套"
        }, 
        {
            "id": 6,
            "pid": 0,
            "name": "玩具"
        },
        {

            "id": 7,
            "pid": 0,
            "name": "手机"
        }
    
    ], "goods": [
        {
            "id": 1,
            "classify": "3",
            "title": "海尔空调",
            "price": 2000
        },        {
            "id": 2,
            "classify": "3",
            "title": "格力空调",
            "price": 1800
        },
        {
            "id": 3,
            "classify": "7",
            "title": "小米新手机",
            "price": 2990
        },
        {
            "id": 4,
            "classify": "7",
            "title": "华为新手机",
            "price": 3600
        }
    ]
}

2.2 一级分类导航切换高亮效果

vim GoodList01.js

import React, { Component } from 'react';
import axios from 'axios'

export class GoodsList01 extends Component {

  constructor(){
    super();
    this.state = {
      navs: [], //所有分类数据
      goods: [], //所有商品数据,
      selId: 1 //被选中的id
    }
  }

  componentDidMount(){
    axios.get("http://localhost:3000/data.json")
    .then((resp)=>{
      console.log(resp.data)
      this.setState({
        navs: resp.data.navs
      })
    })
  }

  render() {
    const { navs, goods, selId } = this.state;
    return (
      <div>
        {navs.map((item, index) =>{
          if (item.pid === 0){
            return (
              <div 
                key={index}
                style={{color:selId === item.id ? 'red':"#999"}}
                onClick={()=>{
                  this.setState({
                    selId: item.id
                  })
                  }
                }
                >
                {item.name}
              </div>
            )
          }else {
            return (
              <div key={index}>
              </div>
            )
          }
        })}
      </div>
    )
  }
}

export default GoodsList01

结果:
在这里插入图片描述

2.3 显示二级分类导航

vim GoodList01.js

import React from 'react';
import axios from 'axios'

export class GoodsList01 extends React.Component {

  constructor(){
    super();
    this.state = {
      navs: [], //所有分类数据
      goods: [], //所有商品数据,
      selId: 1 //被选中的id
    }
  }

  componentDidMount(){
    axios.get("http://localhost:3000/data.json")
    .then((resp)=>{
      console.log(resp.data)
      this.setState({
        navs: resp.data.navs
      })
    })
  }

  render() {
    const { navs, selId } = this.state;
    return (
      <div>
        <div style={{display:"flex", flexDirection:"row"}}>
        {navs.map((item, index) =>{
          if (item.pid === 0){
            return (
              <div 
                key={index}
                style={{color:selId === item.id ? 'red':"#999"}}
                onClick={()=>{
                  this.setState({
                    selId: item.id
                  })
                  }
                }
                >
                {item.name}&nbsp;
              </div>
            )
          }else {
            return (
              <div key={index}>
              </div>
            )
          }
        })}
        </div>
        <hr />
        {navs.map((item, index)=>{
          if(item.pid === selId){
            return (
              <div key={index}> 
                {item.name}
              </div>
            )
          }else {
            return (
              <div> </div>
            )
          }
        })
        }

      </div>
    )
  }
}
export default GoodsList01

最下面新加一个 navs.map((item, index) 即可

2.4 路由跳转到二级导航的商品列表

vim Nav01.js

import React from 'react';
import axios from 'axios';
import { Link } from 'react-router-dom'

export class Nav01 extends React.Component {

  constructor(){
    super();
    this.state = {
      navs: [], //所有分类数据
      goods: [], //所有商品数据,
      selId: 1 //被选中的id
    }
  }

  componentDidMount(){
    axios.get("http://localhost:3000/data.json")
    .then((resp)=>{
      // console.log(resp.data)
      this.setState({
        navs: resp.data.navs
      })
    })
  }

  render() {
    const { navs, selId } = this.state;
    return (
      <div>
        <div style={{display:"flex", flexDirection:"row"}}>
        {navs.map((item, index) =>{
          if (item.pid === 0){
            return (
              <div 
                key={index}
                style={{color:selId === item.id ? 'red':"#999"}}
                onClick={()=>{
                  this.setState({
                    selId: item.id
                  })
                  }
                }
                >
                {item.name}&nbsp;
              </div>
            )
          }else {
            return (
              <div key={index}>
              </div>
            )
          }
        })}
        </div>
        <hr />
        {navs.map((item, index)=>{
          if(item.pid === selId){
            return (
              <Link key={index} to={`/list/${item.id}`}>
                <div key={index}> 
                  {item.name}
                </div>
              </Link>
            )
          }else {
            return (
              <div key={index}> 
              </div>
            )
          }
        })
        }

      </div>
    )
  }
}

export default Nav01

vim GoodsList.js

import React, { Component } from 'react';
import axios from 'axios';

export class GoodsList extends Component {
  constructor() {
    super();
    this.state = {
      goods: []
    }
  }

  UNSAFE_componentWillMount(){
    // console.log(this.props)
    let id = this.props.match.params.id;
    console.log(id)
    axios.get("http://localhost:3000/data.json")
    .then((resp)=>{
      let goodsList = resp.data.goods;
      let goods = [];
      goodsList.map((item)=>{
          if(item.classify === id){
            goods.push(item)
          }
          return goods
      })
      this.setState({
        goods
      })
    })
  }
    
  render() {
    return (
        <div>
          <div onClick={()=>{
            window.history.back()
          }}>返回</div>
          This is GoodsList!
          {this.state.goods.map((item, index)=>{
            return (
              <div key={index}>
                {item.title},{item.price}
              </div>
            )
          })}
        </div>
    )
  }
}

export default GoodsList

vim App.js

import React from "react";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import GoodsList from "./pages/GoodsList";
import Nav01 from "./pages/Nav01";

class App extends React.Component{

    render(){
        return (
            <BrowserRouter>
                <Switch>
                    <Route path="/list/:id" component={GoodsList} />
                    <Route exact path="/" component={Nav01} />
                </Switch>
            </BrowserRouter>
        )
    }
}

export default App

结果:
在这里插入图片描述
点击 手机-小米手机
在这里插入图片描述

2.5 商品搜索

vim Search.js

import React, { Component } from 'react';
import axios from 'axios';

export class Search extends Component {
    constructor(){
        super();
        this.state = {
          goods: [], //所有商品数据,
          inputValue: '',
          resultList: []
        }
      }
    
    componentDidMount(){
    axios.get("http://localhost:3000/data.json")
    .then((resp)=>{
        // console.log(resp.data)
        this.setState({
        goods: resp.data.goods
        })
    })
    }

    render(){
        return (
        <div>
            <div >
            <input value={this.state.inputValue} onChange={(e)=>{
                this.setState({
                    inputValue: e.target.value
                })
            }}/>
            <button onClick={this.search.bind(this)}>搜索</button>
            </div>
            {this.state.resultList.map((item, index)=>{
                return (
                    <div key={index}> 
                        {item.title},¥{item.price}
                    </div>
                )
            })}
        </div>
        )
    }

    search(){
        let keyword = this.state.inputValue;
        console.log(keyword)
        let goods =  this.state.goods;
        let resultList = []
        goods.map((item)=>{
            if(item.title.includes(keyword)){
                resultList.push(item)
            }
        })
        this.setState({resultList})
    }
}

export default Search

vim Nav01.js

 render() {
    const { navs, selId } = this.state;
    return (
      <div>
        <Link to={`/search`}>搜索</Link>
        <div style={{display:"flex", flexDirection:"row"}}>
        {navs.map((item, index) =>{
		***
		}}
		</div>
	  </div>
	)
 }

vim App.js

class App extends React.Component{

    render(){
        return (
            <BrowserRouter>
                <Switch>
                    <Route path="/search" component={Search}></Route>
                    <Route path="/list/:id" component={GoodsList} />
                    <Route exact path="/" component={Nav01} />
                </Switch>
            </BrowserRouter>
        )
    }
}

结果:
主界面
在这里插入图片描述
点击搜索界面
在这里插入图片描述
搜索产品
在这里插入图片描述

3 注意事项

  1. 安装包
    npm i axios --save
    npm i react-router-dom@5.2.0 --save
    
  2. 错误
    Array.prototype.map() expects a return value from arrow function 
    
    goodsList.map((item)=>{
           if(item.classify === id){
             goods.push(item)
           }
           return goods
       })
    
  3. child in a list should have a unique “key” prop
    {navs.map((item, index)=>{
          if(item.pid === selId){
            return (
              <Link key={index} to={`/list/${item.id}`}>
                <div key={index}> 
                  {item.name}
                </div>
              </Link>
            )
          }else {
            return (
              <div key={index}> 
              </div>
            )
          }
        })
        }
    
  4. 当前选中二级分类后产品在 /list/{number} 页面显示, 也可以在Nave01.js 下面再加一层展示具体产品列表的功能。
  5. 当前只是模拟商城的基础功能,后续可以在此基础上新增 登录注册、加购物车流程;也可以通过本案例学习完成一个 TodoList 小应用。

4 说明

软件版本:
node 16.13.1
create-react-app 5.0.0
react-router-dom@5.2.0
axios 0.25.0
参考文档:
React基础入门+综合案例
react 官网
React基础入门教程
withRouter’ is not exported from ‘react-router-dom’

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

react基础06--react综合案例-电商网站导航 的相关文章

  • 使用 Enzyme 测试 `React.createRef` api

    我想测试下面的类 它使用React createRef api 不过 快速搜索并没有发现任何这样做的例子 有人成功过吗 我该如何嘲笑裁判 理想情况下我想使用shallow class Main extends React Component
  • webpack 4 React loadable 不会根据卡盘点分割供应商

    我目前正在使用 webpack 4 和 React loadable 来创建块 它实际上分块取决于断点 然而 供应商规模保持不变 React loadable 还不支持 webpack 4 吗 或者我缺少一些设置 css 实际上似乎被分成了
  • 自定义rc-time-picker的样式

    我在用rc time picker我的项目的包 但我在自定义样式时遇到问题pop up of my time picker成分 这是我的组件的屏幕截图 首先 我需要更改时间的背景颜色item在当时li from light grey 在屏幕
  • 当文本输入聚焦在 React Native for Android 的底部工作表上时,视图移出屏幕

    我正在使用图书馆 https github com osdnk react native reanimated bottom sheet https github com osdnk react native reanimated bott
  • 在 ReactJS 中创建动态目录

    我有一个组件 它代表一个页面 其中有多个SectionHeader 组件作为该页面的子组件 我想通过检查 Page 的子项 SectionHeaders 来动态创建目录
  • 如何在执行新操作时取消先前操作的执行?

    我有一个动作创建器 它会进行昂贵的计算 并在每次用户输入内容时调度一个动作 基本上是实时更新 但是 如果用户输入多个内容 我不希望之前昂贵的计算完全运行 理想情况下 我希望能够取消执行先前的计算并只执行当前的计算 没有内置功能可以取消Pro
  • redux 和 React 中减速器的先前状态

    这是我的减速器的样子 export default function catalogReducer state initialState catalogItems action switch action type case types L
  • redux-observable 中的独立链取消?

    我是 RxJS 新手 在我的应用程序中 我需要独立取消延迟操作 Here s http jsbin com gayoti edit js output一个工作示例 延迟为 3 秒 但是当我选择删除多个项目并取消其中一项时 然后一次全部取消
  • React Typescript - 在路由中传递时如何将类型添加到 location.state

    当我将react router props发送到路由中的组件时 我收到错误 因为我有特定的状态 我传递了该组件 但错误显示在我的路由中 这是路线代码
  • Next.js - 如何使用 Provider 来包装路由并使用 Context 和 Hooks

    我在 create react app 中编写了类似于以下的代码 我想知道 next js 的等效代码 下面的代码是我尝试拥有一个可用于所有页面的全局上下文 提供者包装链接 我没有收到任何错误 问题出在里面about当我期望上下文状态时 页
  • 如何在 React 组件中使用 CDN

    我正在尝试使用基于 D3 构建的库 称为 Greuler 来动态渲染图形 它的 npm 包似乎已损坏 当我改用 Greuler CDN 时 index html 中的测试图终于起作用了 但是 我正在开发一个 React 应用程序 并且我希望
  • React Native 中循环 Json 并显示

    How do I go about looping the result i retrieved from Json render function console log this state list contents
  • 具有多种布局的 React Router v4

    我想在我的公共布局中渲染一些路线 并在我的私人布局中渲染一些其他路线 有没有一种干净的方法可以做到这一点 显然不起作用的示例 但我希望大致解释我正在寻找的内容
  • React:在哪里扩展对象原型

    我使用创建了一个纯 React 应用程序创建反应应用程序 https github com facebookincubator create react app 我想延长String类并在一个或多个组件中使用它 例如 String prot
  • useState 以 `new` 关键字作为参数

    我正在构建一个单独的服务来处理复杂的事情 该服务是一个类 只是为了测试建议 我在一个内部模拟useState 重点是我忘记了一个console log在构造函数内部 并意识到类构造函数在组件重新渲染时被调用多次 这种行为不会导致意外的行为或
  • 通过 Javascript 填充 ReactJS HTML 表单

    我正在开发一个应用程序 在打开第 3 方网站后 我可以在浏览器上下文中运行我自己的 Javascript 作为一个基于reactjs构建并具有登录表单的示例网站 您可以参考此链接 我正在尝试在reactjs生成的表单中填写用户名和密码 但是
  • 如何使用 next.js 将动态 html 元素注入到页面?

    如何使用next js动态注入html元素到页面 这些元素未知类型 例如 输入 复选框 img 使用返回 json 类型的 api 指定此元素 如下所示 id rooms title Rooms order 1 type string wi
  • 如何使用 Jest 测试 React 渲染的异步数据?

    我使用 React 进行渲染 使用 Jest Jasmine 进行测试 我用旧的 Jest Jasmine 编写了测试waitsFor and runs但这些现在在 Jasmine 2 中已经消失了 我不知道如何用新的替换done asyn
  • React/Redux bundle.js 太大

    我有一个小型的 React 项目 Webpack生成的bundle js大小为6 3Mb 如何将大小减小到 github webpack config js module exports devtool inline source map
  • React router.push 和 router.replace 之间的区别?

    有什么区别React 路由器推送 and 路由器 替换 路由器历史记录就像一个stack of routes 当您使用router replace 您将覆盖堆栈的顶部 当使用router push 它在顶部添加了一条新路线stack 路由器

随机推荐

  • 苏州吴江区实现首单跨区域数字人民币试点场景应用

    作为数字人民币试点的首批城市 苏州一直在数字人民币应用场景的落地方面进展迅速 其中 苏州相城区在全市率先开展数字人民币场景建设及试点 截至目前 已开放试点场景7500余个 占全市总数近50 并在全国率先落地交通补贴批量代发 房屋契税缴纳 智
  • python num循环怎么从1开始

    如何实现python for循环从1开始 range 函数的作用和用法 编写一个从数值1开始的循环 执行后得到的结果 其他注意事项
  • 在OTFS学习中的一些总结

    双选特性 多径传播 gt 时延 gt 频率选择性 时延的倒数为相干带宽 在频域内信道相应的幅值大概保持不变的一段频率称为相干带宽 当信号的带宽小于相干带宽 或者说信号的传输时间 周期 大于时延拓展 信号之间没有干扰 我们认为信号是没有失真的
  • Win10下Anaconda使用conda activate激活环境出错

    直接输入conda activate pytorch 报如下错误 解决方法 1 在base路径下先输入activate 提示如下 2 再输入conda activate base 激活base环境 3 在输入conda activate p
  • [python知识] 爬虫知识之BeautifulSoup库安装及简单介绍

    一 前言 在前面的几篇文章中我介绍了如何通过Python分析源代码来爬取博客 维基百科InfoBox和图片 其文章链接如下 python学习 简单爬取维基百科程序语言消息盒 Python学习 简单网络爬虫抓取博客文章及思想介绍 python
  • awk使用shell变量,shell获取awk中的变量值

    awk使用shell变量 shell获取awk中的变量值 2012 04 13 09 36 28 分类 LINUX 字号 订阅 原文 http renyongjie668 blog 163 com blog static 160053120
  • 今天面试招了个18K的人,从腾讯出来的果然都有两把刷子···

    公司前段时间缺人 也面了不少测试 前面一开始瞄准的就是中级的水准 也没指望来大牛 提供的薪资在15 20k 面试的人很多 但平均水平很让人失望 看简历很多都是4年工作经验 但面试中 不提测试工具 仅仅基础的技术很多也知之不详 多数人数年的工
  • Android 系统启动流程简介

    1 Init 进程启动流程 2 Zygote启动流程 3 SystemServer启动流程 1 Init 进程启动流程 Android启动流程 init进程 gt Zygote进程 gt SystemServer进程 gt 各种应用进程 I
  • [源码解析] NVIDIA HugeCTR,GPU 版本参数服务器---(7) ---Distributed Hash之前向传播

    Python微信订餐小程序课程视频 https edu csdn net course detail 36074 Python实战量化交易理财系统 https edu csdn net course detail 35475 源码解析 NV
  • 【Php】PhpSpreadsheet安装的坑怎么这么多!

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 人是代码非 一 PhpSpreadsheet不安装直接用行不行 二 安装的坑 1 缺少fileinfo扩展 2 下载中断 3 proc open函数被禁用 4 co
  • Jmeter 集合点详细讲解

    集合点 让所有请求在不满足条件的时候处于等待状态 如 我集合点设置为50 那么不满足50个请求的时候 这些请求都会集合在一起 处于等待状态 当达到50的时候 就一起执行 从而达到并发的效果 那么Jmeter中可以通过同步定时器Synchro
  • Mybatis

    最近又遇到mybatis的问题了 所以把之前写的和补充的笔记一起放上来 一 动态sql 在编写项目的时候经常需要拼接一些复杂的SQL语句 而拼接过程中很容易导致错误 而Mybatis的动态SQL功能正好能够解决这种问题 可以通过使用 if
  • 【长文预警】美团联合创始人王慧文清华产品课

    前言 一 成功和失败的产品 一般来说在一个领域里一款产品的成功对应着无数产品的失败 根据老王个人的经验 成功和失败的比例大约是1 30 失败的原因多种多样 有些啥都没做对 有些作对了一部分 这里列举的失败案例主要讲做对了一部分的 准确说算是
  • sonar.java.binaries的配置

    从sonarQube 4 12开始 sonar将会进行程序的动态检查 不配置sonar java binaries属性将会出错 From SonarJava version 4 12 binary files are required fo
  • 在 Mac 上使用 VMware 安装 Windows 11

    因为项目原因 需要在 windows 环境下测试一下 electron 的表现 于是就记录一下在 mac 虚拟机上安装 windows 的体验 总体来说难度不大 我电脑的情况 2020 款 macbook pro 16g 512g 前期准备
  • golang版本管理gvm

    今天小土带来一篇关于Go版本管理器gvm的小短文 废话不多说 开始安装 安装 如果你使用的mac mac 需要先安装xcode select 没安装过的同学可以按照如下命令进行执行安装 这里不做太多说明了 xcode select inst
  • 地震逃生【最大流模板题】

    题目链接 P1343 地震逃生 简单的最大流的模板 小心 0 的RE情况 读题 另外 写的是ISAP include
  • 微信小程序授权登录页面(有提示窗)

    微信小程序授权登录 有弹窗提示 1 效果显示 1 1 授权登录页面 1 2 授权登录提示弹窗 1 3 拒绝授权登录 1 4 允许登录后 跳转到小程序首页 2 代码 2 1 wxml 文件
  • 日志审计功能实现

    1 前言 日志审计功能就是将用户进行的增加 修改和删除操作内容 操作方法 操作人以及操作时间等统一格式后集中放入数据库存储 这样做是为了提高系统的安全性 方便系统发生事故后的溯源和恢复 2 日志审计实现 2 1 设计数据库 下图为数据库中的
  • react基础06--react综合案例-电商网站导航

    react基础06 react综合案例 电商网站导航 1 介绍 2 案例设计模块 2 1 分类导航数据模型设计 2 2 一级分类导航切换高亮效果 2 3 显示二级分类导航 2 4 路由跳转到二级导航的商品列表 2 5 商品搜索 3 注意事项