千峰React:案例二

完成对html文档还有css的引入,引入一下数据:

javascript 复制代码
import { func } from 'prop-types'
import './购物车样式.css'
import axios from 'axios'
import { useImmer } from 'use-immer'
import { useEffect } from 'react'

function Item() {
  return (
    <li className='active'>
      <h3>香蕉</h3>
      <p>单价:5</p>
      <p>
        数量:
        <span className='remove'>-</span>
        <span>1</span>
        <span className='add'>+</span>
      </p>
      <div className='cartbtn'>取消购买</div>
    </li>
  )
}

function Cart() {
  const [list, setList] = useImmer([])
  useEffect(() => {
    axios.get('../public/cartData.json').then((res) => {
      console.log(res)
    })
  })
  return (
    <div className='cart'>
      <ul>
        <Item />
      </ul>
      <div className='all'>
        总金额:<span>5</span>元
      </div>
    </div>
  )
}
export default Cart

然后判断数据是否存在:

刚刚数字一直在疯涨,导致他疯涨的原因是我的useEffect没加依赖数组,还有axios的url,如果我的数据文件在public里,可以直接从根目录访问(好像学过),要写成这样👇

javascript 复制代码
useEffect(() => {
    axios.get('/cartData.json').then((res) => {
        if (res.data.errcode === 0) {
            //map来给购物车添加
            setList(res.data.list.map((item) => ({...item,active:false})))
     }
    })
  },[])

还有一个无语的bug是箭头函数的return每次都会加大括号忘记加retuen,不加return又会格式化到下一行

对每个按钮绑上onClick事件,再给每个按钮绑上id:

javascript 复制代码
import { func } from 'prop-types'
import './购物车样式.css'
import axios from 'axios'
import { useImmer } from 'use-immer'
import { useEffect } from 'react'

function Item({id,name,price,number,active,handleAdd}) {
    return (
      //active初始根据active的值判定
      <li className={ active?'active':''}>
          <h3>{ name}</h3>
          <p>单价:{ price}</p>
      <p>
        数量:
        <span className='remove'>-</span>
              <span>{ number}</span>
        <span className='add'>+</span>
      </p>
            <div className='cartbtn' onClick={()=>handleAdd(id)}>{ active?'取消购买':'添加购物车'}</div>
    </li>
  )
}

function Cart() {
  const [list, setList] = useImmer([])
  useEffect(() => {
    axios.get('/cartData.json').then((res) => {
      if (res.data.errcode === 0) {
        //map来给购物车添加
        setList(res.data.list.map((item) => ({ ...item, active: false })))
      }
    })
  }, [])
    const handleAdd=(id) => {
        setList((draft) => {
            const value = draft.find((item) => item.id === id)
            value.active=!value.active
        })
    }
  return (
    <div className='cart'>
      <ul>
              {list.map((item) => <Item key={item.id} {...item} handleAdd={handleAdd} />)}
      </ul>
      <div className='all'>
        总金额:<span>5</span>元
      </div>
    </div>
  )
}
export default Cart

增加修改数量的功能

javascript 复制代码
import { func } from 'prop-types'
import './购物车样式.css'
import axios from 'axios'
import { useImmer } from 'use-immer'
import { useEffect } from 'react'

function Item({
  id,
  name,
  price,
  number,
  active,
  handleAdd,
  handleNumberChange,
}) {
  return (
    //active初始根据active的值判定
    <li className={active ? 'active' : ''}>
      <h3>{name}</h3>
      <p>单价:{price}</p>
      <p>
        数量:
        <span className='remove' onClick={()=>handleNumberChange(id, -1)}>
          -
        </span>
        <span>{number}</span>
        <span className='add' onClick={()=>handleNumberChange(id, +1)}>
          +
        </span>
      </p>
      <div className='cartbtn' onClick={() => handleAdd(id)}>
        {active ? '取消购买' : '添加购物车'}
      </div>
    </li>
  )
}

function Cart() {
  const [list, setList] = useImmer([])
  useEffect(() => {
    axios.get('/cartData.json').then((res) => {
      if (res.data.errcode === 0) {
        //map来给购物车添加
        setList(res.data.list.map((item) => ({ ...item, active: false })))
      }
    })
  }, [])
  const handleAdd = (id) => {
    setList((draft) => {
      const value = draft.find((item) => item.id === id)
      value.active = !value.active
    })
  }
  const handleNumberChange = (id, num) => {
    setList((draft) => {
      const value = draft.find((item) => item.id === id)
      if (value.number === 0 && num < 0) {
        return
      }
      value.number += num
    })
  }
  return (
    <div className='cart'>
      <ul>
        {list.map((item) => (
          <Item
            key={item.id}
            {...item}
            handleAdd={()=>handleAdd(item.id)}
            handleNumberChange={(num)=>handleNumberChange(item.id,num)}//注意传参问题,前面的num是onClick传递的
          />
        ))}
      </ul>
      <div className='all'>
        总金额:<span>5</span>元
      </div>
    </div>
  )
}
export default Cart

如果你写成 handleNumberChange={() => handleNumberChange(item.id, num)}num 的值无法动态传递,因为 num 是在 Item 组件的 onClick 事件中才确定的。

加入计算总金额功能,用filter选择被加入购物车的商品,reduce计算

javascript 复制代码
 const all = list
    .filter((item) => item.active)
    .reduce((init, item) => init + item.number * item.price, 0)

每次改变状态时都会重新渲染,提升性能,使用memo,只有props不同的时候才会渲染

里面包的是函数,之前学的useCallback可以解决函数被Object.Is()判别为不同的问题

javascript 复制代码
import { func } from 'prop-types'
import './购物车样式.css'
import axios from 'axios'
import { useImmer } from 'use-immer'
import { memo, useCallback, useEffect } from 'react'

const Item = memo(function Item({
  id,
  name,
  price,
  number,
  active,
  handleAdd,
  handleNumberChange,
}) {
  console.log('如果被渲染了,我就会出现')

  return (
    //active初始根据active的值判定
    <li className={active ? 'active' : ''}>
      <h3>{name}</h3>
      <p>单价:{price}</p>
      <p>
        数量:
        <span className='remove' onClick={() => handleNumberChange(id, -1)}>
          -
        </span>
        <span>{number}</span>
        <span className='add' onClick={() => handleNumberChange(id, +1)}>
          +
        </span>
      </p>
      <div className='cartbtn' onClick={() => handleAdd(id)}>
        {active ? '取消购买' : '添加购物车'}
      </div>
    </li>
  )
})

function Cart() {
  const [list, setList] = useImmer([])
  const all = list
    .filter((item) => item.active)
    .reduce((init, item) => init + item.number * item.price, 0)
  useEffect(() => {
    axios.get('/cartData.json').then((res) => {
      if (res.data.errcode === 0) {
        //map来给购物车添加
        setList(res.data.list.map((item) => ({ ...item, active: false })))
      }
    })
  }, [])
  const handleAdd = useCallback((id) => {
    setList((draft) => {
      const value = draft.find((item) => item.id === id)
      value.active = !value.active
    })
  })
  const handleNumberChange = useCallback((id, num) => {
    setList((draft) => {
      const value = draft.find((item) => item.id === id)
      if (value.number === 0 && num < 0) {
        return
      }
      value.number += num
    })
  })
  return (
    <div className='cart'>
      <ul>
        {list.map((item) => (
          <Item
            key={item.id}
            {...item}
            handleAdd={() => handleAdd(item.id)}
            handleNumberChange={(num) => handleNumberChange(item.id, num)} //注意传参问题,前面的num是onClick传递的
          />
        ))}
      </ul>
      <div className='all'>
        总金额:<span>{all}</span>元
      </div>
    </div>
  )
}
export default Cart

这下基本就写完了

相关推荐
Enti7c2 小时前
什么是 jQuery
前端·javascript·jquery
cafehaus2 小时前
关于JavaScript性能问题的误解
开发语言·javascript·ecmascript
taopi20243 小时前
若依vue plus环境搭建
前端·javascript·vue.js
李奶酪3 小时前
React Native 原理
javascript·react native·react.js
十八朵郁金香4 小时前
深入浅出理解编译器:前端视角
开发语言·前端·javascript
GISer_Jing6 小时前
[React]Render Props、自定义Hooks和Context API优化详解
前端·javascript·react.js
CaptainDrake7 小时前
React低代码项目:用户登陆
前端·react.js·低代码
CaptainDrake8 小时前
React低代码项目:Redux 状态管理
前端·react.js·低代码
m0_zj8 小时前
30.[前端开发-JavaScript基础]Day07-数组Array-高阶函数-日期Date-DOM
开发语言·前端·javascript
OrzR38 小时前
Vue Grid Layout 拖拽改变元素位置和大小的一个好工具
前端·javascript·vue.js