Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 097c5c7

Browse files
完善搜索功能
1 parent ae2e138 commit 097c5c7

File tree

7 files changed

+102
-22
lines changed

7 files changed

+102
-22
lines changed

‎README.md‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,14 @@ const B = () => {
4848
```
4949

5050
- `useEffect` 解决组件产生的副作用
51+
默认情况下,`useEffect()`中的函数,会在组件渲染完成后调用,
52+
并且是每次渲染完成后都会调用
53+
`useEffect()`可以传递一个第二个参数,
54+
第二个参数是一个数组,在数组中可以指定 `Effect` 的依赖项
55+
指定后,只有当依赖发生变化时,`Effect` 才会被触发
56+
通常会将 `Effect` 中使用的所有的局部变量都设置为依赖项
57+
这样一来可以确保这些值发生变化时,会触发 `Effect` 的执行
58+
`setState()`是由钩子函数 `useState()`生成的
59+
`useState()`会确保组件的每次渲染都会获取到相同 `setState()`对象
60+
所以 `setState()`方法可以不设置到依赖中
61+
如果依赖项设置了一个空数组,则意味 `Effect` 只会在组件初始化时触发一次

‎src/App.js‎

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,14 @@ const MEALS_DATA = [
5555
]
5656

5757
function App () {
58-
const [mealsData] = useState(MEALS_DATA)
58+
const [mealsData,setMealsData] = useState(MEALS_DATA)
5959
const [cartData, setCartData] = useState({
6060
items: [],
6161
totalPrice: 0,
6262
amount: 0
6363
})
6464

65+
// 添加商品
6566
const addItem = (item) => {
6667
let newMeal = { ...cartData }
6768
newMeal.amount++
@@ -76,6 +77,7 @@ function App () {
7677
setCartData(newMeal)
7778
}
7879

80+
// 删除商品
7981
const removeItem = (item) => {
8082
let newMeal = { ...cartData }
8183
newMeal.totalPrice -= item?.price
@@ -87,11 +89,36 @@ function App () {
8789
setCartData(newMeal)
8890
}
8991

92+
// 清空购物车
93+
const clearCart = () => {
94+
let cart = {
95+
items: [],
96+
amount: 0,
97+
totalPrice: 0
98+
}
99+
let meals = [...mealsData]
100+
meals.forEach(meal => delete meal.count)
101+
setCartData(cart)
102+
}
103+
104+
// 搜索
105+
const filterData = (keyWord) => {
106+
if (!keyWord) {
107+
setMealsData(MEALS_DATA)
108+
} else {
109+
110+
let meals = [...MEALS_DATA]
111+
meals = meals.filter(meal => meal.title.indexOf(keyWord) > -1)
112+
// console.log(meals)
113+
setMealsData(meals)
114+
}
115+
}
116+
90117
return (
91-
<cartContext.Provider value={{ ...cartData, addItem, removeItem }}>
118+
<cartContext.Provider value={{ ...cartData, addItem, removeItem, clearCart }}>
92119
<ConfigProvider theme={{ token: { colorPrimary: '#ffcd00' } }}>
93120
<div style={{ width: '750rem', height: '100vh', overflow: 'hidden', position: 'relative' }}>
94-
<Search></Search>
121+
<SearchfilterFn={filterData}></Search>
95122
<Meals meals={mealsData}></Meals>
96123
<Cart></Cart>
97124
</div>

‎src/components/cart/detail/index.js‎

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,36 @@
1-
import React from 'react'
1+
import React,{useContext} from 'react'
22
import { DeleteOutlined } from '@ant-design/icons'
33
import detailCss from './index.module.css'
44
import Backdrop from '../../ui/backdrop'
55
import Counter from '../../meals/counter'
6+
import cartCtx from '../../../store/cart'
67

78
function Detail ({ meals }) {
9+
10+
const ctx = useContext(cartCtx)
11+
812
return (
913
<Backdrop>
10-
<div className={detailCss.detailBox}>
14+
<div className={detailCss.detailBox}onClick={(e)=>{e.stopPropagation()}}>
1115

1216
<div className={detailCss.top}>
1317
<p className={detailCss.title}>餐品详情</p>
14-
<div className={detailCss.del}><DeleteOutlined className={detailCss.delIcon} />清空购物车</div>
18+
<div className={detailCss.del}onClick={ctx.clearCart}><DeleteOutlined className={detailCss.delIcon} />清空购物车</div>
1519
</div>
16-
<div>
20+
<divclassName={detailCss.detailItem}>
1721
{
18-
meals.map(meal =>{
19-
<div className={detailCss.item}>
22+
meals.map(meal =>
23+
<div className={detailCss.item}key={meal.id}>
2024
<img src={meal.img} alt={meal.title} className={detailCss.img} />
21-
<div>
25+
<divclassName={detailCss.desc}>
2226
<div className={detailCss.name}>{meal.title}</div>
2327
<div className={detailCss.priceBox}>
2428
<div className={detailCss.price}>\{meal.price * meal.count}</div>
2529
<Counter meal={meal}></Counter>
2630
</div>
2731
</div>
2832
</div>
29-
})
33+
)
3034
}
3135
</div>
3236
</div>

‎src/components/cart/detail/index.module.css‎

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
.detailBox {
22
position: absolute;
33
bottom: 0;
4-
max-height: 70%;
4+
/* max-height: 70%; */
55
width: 100%;
66
box-sizing: border-box;
77
background-color: #fff;
88
border-top-left-radius: 30rem;
99
border-top-right-radius: 30rem;
10-
overflow: auto;
10+
/* overflow: auto; */
1111
padding: 20rem;
1212
}
13+
.detailItem {
14+
max-height: 50vh;
15+
overflow: auto;
16+
padding-bottom: 120rem;
17+
}
1318
.top {
1419
display: flex;
1520
justify-content: space-between;
1621
align-items: center;
22+
height: 60rem;
1723
}
1824
.title {
1925
color: #3223223;
20-
font-size: 20rem;
26+
font-size: 28rem;
2127
}
2228
.del {
2329
color: #aaa;
@@ -32,16 +38,24 @@
3238
}
3339
.item {
3440
display: flex;
41+
border-bottom: 1rem solid #eee;
42+
}
43+
.desc {
44+
flex: 1;
45+
display: flex;
46+
flex-direction: column;
47+
justify-content: center;
3548
}
3649
.img {
37-
width: 40rem;
38-
height: 40rem;
50+
width: 120rem;
51+
height: 120rem;
3952
border-radius: 8rem;
4053
margin-right: 10rem;
4154
}
4255
.name {
4356
color: #323232;
44-
font-size: 28rem;
57+
font-size: 30rem;
58+
margin-bottom: 8rem;
4559
}
4660
.priceBox {
4761
display: flex;

‎src/components/cart/index.js‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useContext, useState } from 'react'
1+
import React, { useContext, useEffect,useState } from 'react'
22
import { TabletFilled } from '@ant-design/icons'
33
import cartCss from './index.module.css'
44
import Badge from '../badge'
@@ -13,6 +13,12 @@ function Cart () {
1313
const toggleDetail = () => {
1414
setShowDetails(!showDetails)
1515
}
16+
17+
useEffect(() => {
18+
if (cartData.amount === 0) {
19+
setShowDetails(false)
20+
}
21+
}, [cartData])
1622
return (
1723
<div className={cartCss.cartBox} onClick={toggleDetail}>
1824
{showDetails && <Detail meals={cartData.items}></Detail>}

‎src/components/search/index.js‎

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,30 @@
1-
import React from 'react'
1+
import React,{useEffect,useState} from 'react'
22
import { Input } from 'antd'
33
import { SearchOutlined } from '@ant-design/icons'
44
import searchCss from './index.module.css'
55

6-
function Search () {
6+
function Search ({ filterFn }) {
7+
const [keyWord, setKeyWord] = useState('')
8+
9+
// 使用useEffect进行防抖
10+
useEffect(() => {
11+
12+
const timer = setTimeout(() => {
13+
filterFn(keyWord)
14+
}, 500)
15+
16+
return () => {
17+
clearTimeout(timer)
18+
}
19+
20+
}, [keyWord])
21+
22+
const searchHandle = (e) => {
23+
setKeyWord(e.target?.value?.trim())
24+
}
725
return (
826
<div className={searchCss.search}>
9-
<Input className={searchCss.searchInput} prefix={<SearchOutlined className={searchCss.icon} />} placeholder='请输入关键字'></Input>
27+
<Input onChange={searchHandle}value={keyWord}className={searchCss.searchInput} prefix={<SearchOutlined className={searchCss.icon} />} placeholder='请输入关键字'></Input>
1028
</div>
1129
)
1230
}

‎src/components/ui/backdrop/index.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React,{useContext} from 'react'
1+
import React from 'react'
22
import backdropCss from './index.module.css'
33
import { createPortal } from 'react-dom'
44

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /