当前位置: 首页 > article >正文

千峰React:案例二

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

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里,可以直接从根目录访问(好像学过),要写成这样👇

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:

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

    增加修改数量的功能

    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计算

     const all = list
        .filter((item) => item.active)
        .reduce((init, item) => init + item.number * item.price, 0)

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

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

    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
    

    这下基本就写完了


    http://www.kler.cn/a/572028.html

    相关文章:

  • 【每日学点HarmonyOS Next知识】getContext问题、清除Web缓存、弹层的点击事件透传、去除间隙、侧滑菜单设置
  • 【C++】为什么C++的构造函数不能为虚函数,折钩函数可以为虚函数
  • ChatVLA:基于视觉-语言-动作模型的统一多模态理解与机器人控制
  • python和pycharm安装教程
  • 云服数据存储接口:CloudSever
  • JavaEE_多线程(一)
  • C++中的无锁编程
  • Python Cookbook-3.1 计算昨天和明天的日期
  • 详细分析KeepAlive的基本知识 并缓存路由(附Demo)
  • JavaWeb基础专项复习6(2)——AJAX补充
  • [leetcode]704.二分查找-简单
  • 【Canny 边缘检测详细讲解】
  • 【ORACLE】ORACLE19C在19.13版本前的一个严重BUG-24761824
  • 统计URL出现层级及次数
  • 2025-03-04 学习记录--C/C++-C语言 判断是否是素数
  • C# .NETCore ZipArchive 处理大容量文件导致内存占用高的问题
  • 【YOLO12全网首发】训练+测试行人摔倒
  • json介绍、python数据和json数据的相互转换
  • 华为 VRP 系统简介配置SSH,TELNET远程登录
  • Kubernetes Pod 管理及优化