react基础06--react综合案例-电商网站导航
- 1 介绍
- 2 案例设计模块
- 2.1 分类导航数据模型设计
- 2.2 一级分类导航切换高亮效果
- 2.3 显示二级分类导航
- 2.4 路由跳转到二级导航的商品列表
- 2.5 商品搜索
- 3 注意事项
- 4 说明
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结果:

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}
</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
最下面新加一个 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,) =>{
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>
<hr />
{navs.map((item,)=>{
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
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,)=>{
            return (
              <div key={index}>
                {item.title},{item.price}
              </div>
            )
          })}
        </div>
    )
  }
}
export defaultvim 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
结果:

 点击 手机-小米手机

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,)=>{
                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 defaultvim Nav01.js
render() {
    const { navs, selId } = this.state;
    return (
      <div>
        <Link to={`/search`}>搜索</Link>
        <div style={{display:"flex", flexDirection:"row"}}>
        {navs.map((item,) =>{
        ***
        }}
        </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 注意事项
- 安装包
npm i axios --save
npm
- 错误
Array.prototype.map() expects a return value from arrow function
goodsList.map((item)=>{
if(item.classify === id){
goods.push(item)
}
return goods
})
- child in a list should have a unique “key” prop
{navs.map((item,)=>{
      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>
        )
      }
    })
    }- 当前选中二级分类后产品在 /list/{number} 页面显示, 也可以在Nave01.js 下面再加一层展示具体产品列表的功能。
- 当前只是模拟商城的基础功能,后续可以在此基础上新增 登录注册、加购物车流程;也可以通过本案例学习完成一个 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’
                










