Redux案例实现购物车

Posted 橘猫吃不胖~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redux案例实现购物车相关的知识,希望对你有一定的参考价值。

【Redux案例】实现购物车

1 效果说明

假设我在网购,有两个商品A、B,它们是独立的组件,当我想购买A商品时,我就进入A商品详情页将其添加到购物车,想购买B商品亦然。

初始页面:localhost:3000

点击A商品,进入A商品详情页面,localhost:3000/a

点击添加购物车,有相应的效果:

点击B商品,进入B商品详情页面,localhost:3000/b:

点击添加购物车,有如下效果:

点击删除可以删除任意商品:

在本案例中,购物车是一个共享组件,此时可以使用Redux对购物车实现统一管理。

2 实现代码

2.1 创建项目

使用WebStorm创建一个React项目,安装redux模块

npm install redux

项目的目录结构如下所示:

2.2 store.js

在该文件中主要通过createStore生成store,创建reducer函数,具体代码如下:

import createStore from "redux";

// 定义reducer函数,它有两个参数:state和action
// store是初始的状态,action是派发的动作,goods表示商品
const cartReducer = (state = goods: [], action) => 
    switch (action.type) 
        case "add": // 添加购物车
            // 将state中的所有属性遍历出来(只有goods)
            // goods数组中遍历出来之前的商品,再把新的商品加进去
            return ...state, goods: [...state.goods, action.good];
        case "delete": // 从购物车中删除
            // 获取要删除的商品的索引
            let deleteGoodIndex = action.good.index;
            // 遍历所有的商品信息,并且放在新数组中
            let newGoods = [...state.goods];
            // 将要删除的商品从该数组中删除
            newGoods.splice(deleteGoodIndex, 1);
            return ...state, goods: newGoods; // 删除商品之后的数组覆盖原数组
        default:
            return state;
    


// 创建store对象
let store = createStore(cartReducer);

export default store; // 导出

2.3 A.js

在该文件中主要编写商品A的购物页面,具体代码如下:

import store from "./store";
import React from "react";

// 创建类组件
class A extends React.Component 
    constructor(props) 
        super(props);
        this.state = 
            // 设置当前的初始状态length为store的商品的数量
            length: store.getState().goods.length
        
    

    componentDidMount()  // 页面加载完成后执行该函数
        // 订阅store中state的变化,并返回一个可以取消订阅的对象
        this.unSubscribe = store.subscribe(() =>  // state发生变化后,执行回调函数
            this.setState(
                length: store.getState().goods.length
            )
        )
    

    componentWillUnmount() 
        this.unSubscribe(); // 组件卸载时取消订阅
    

    render() 
        const length = this.state; // 将购买的商品的数量解析出来
        return (
            <div>
                <h2>A商品详情页面</h2>
                <p>当前购物车内商品数量:length</p>
                /*点击按钮后派发add动作,将商品添加到购物车*/
                <button onClick=() => store.dispatch(
                    type: "add",
                    good: 
                        title: `商品$Date.now()`, // 将日期作为商品的编号
                        price: 100
                    
                )>添加购物车
                </button>
            </div>
        )
    


export default A;

2.4 B.js

编写商品B的商品详情页面,与A.js相同,具体代码如下:

import store from "./store";
import React from "react";

class B extends React.Component 
    constructor(props) 
        super(props);
        this.state = 
            length: store.getState().goods.length
        
    

    componentDidMount() 
        this.unSubscribe = store.subscribe(() => 
            this.setState(
                length: store.getState().goods.length
            )
        )
    

    componentWillUnmount() 
        this.unSubscribe();
    

    render() 
        const length = this.state;
        return (
            <div>
                <h2>B商品详情页面</h2>
                <p>当前购物车内商品数量:length</p>
                <button onClick=() => store.dispatch(
                    type: "add",
                    good: 
                        title: `B商品$Date.now()`,
                        price: 150
                    
                )
                >添加购物车
                </button>
            </div>
        )
    


export default B;

2.5 Cart.js

购买商品时,我们不仅能看到商品数量在增加,同时我们也能看到自己买了哪个商品,以及将购买的商品删除,该文件主要实现这个功能,具体代码如下:

import store from "./store";
import React from "react";

class Cart extends React.Component 
    constructor(props) 
        super(props);
        this.state = 
            goods: store.getState().goods // 获取当前购买的商品列表
        
    

    componentDidMount()  // 页面加载完成后执行该函数
        this.unSubscribe = store.subscribe(() => 
            // 当state发生变化时执行回调函数
            this.setState(
                goods: store.getState().goods
            )
        )
    

    componentWillUnmount() 
        this.unSubscribe(); // 取消订阅
    

    render() 
        const goods = this.state; // 将商品列表获取出来
        return (
            <ul>
                /*将商品遍历出来并显示在页面上*/
                
                    goods.map((good, index) => 
                        return (
                            <li key=index>
                                /*good.title是在A.js和B.js中定义的商品名称*/
                                <span>good.title</span>
                                &nbsp;&nbsp;&nbsp;
                                <button onClick=() => store.dispatch(
                                    type: "delete",
                                    good: index // 将当前要删除的商品的索引派给good
                                )>删除
                                </button>
                            </li>
                        )
                    )
                
            </ul>
        )
    


export default Cart;

2.6 App.js

在App.js中主要进行路由配置,代码如下:

import logo from './logo.svg';
import './App.css';
import NavLink, Route from "react-router-dom";
import B from "./components/B";
import A from "./components/A";
import Cart from "./components/Cart";


function App() 
    return (
        <div className="App">
            <header className="App-header">
                <img src=logo className="App-logo" alt="logo"/>
                <div>
                    <NavLink to="/a">A商品</NavLink>
                    &nbsp;&nbsp;&nbsp;
                    <NavLink to="/b">B商品</NavLink>
                </div>
                <Route path="/a" component=A/>
                <Route path="/b" component=B/>
                <Cart/>
            </header>
        </div>
    );


export default App;

2.7 index.js

由于使用了Navlink,因此需要用BrowserRouter组件将App包起来。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import BrowserRouter from "react-router-dom";

ReactDOM.render(
    <BrowserRouter>
        <App/>
    </BrowserRouter>,
    document.getElementById('root')
);
reportWebVitals();

以上是关于Redux案例实现购物车的主要内容,如果未能解决你的问题,请参考以下文章

React-Redux 知识点 及 实现数据共享案例

React Redux:reducers 是不是应该包含任何逻辑

使用react+redux实现弹出框案例

阶段一-02.分类,推荐,搜索,评价,购物车开发-第2章 商品推荐+搜索功能实现-2-3 搜索 - 商品详情功能分析

P07:用useReducer实现Redux效果的小案例

微信小程序结合原生JS实现电商模板