react使用redux操作購物車數據
自己在工作之余寫的一個商場Demo,用的react+Antd,后端使用的是nodejs,數據庫是mysql,這邊只介紹使用redux對購物車的操作,也並不會對redux的使用進行解釋。
我這邊創建了四個文件action.js、reducers.js、store.js、visibility.js,作用呢分別是存放事件發生的動作、應用狀態的變化如何響應 actions 並發送到 store 、將action和reducer聯系在一起、存放用到的一些常量。話不多說,直接貼代碼
store.js
import { createStore, compose, applyMiddleware } from 'redux';
import thunk from 'redux-thunk'; // 處理異步請求的數據,它允許你的action可以返回函數
import getWantData from './reducers';
const store = createStore(getWantData, compose(
applyMiddleware(thunk)
));
export default store;
visibility.js
export const SELECT_ALL_SHOP = 'SELECT_ALL_SHOP'; // 購物車所有商品
export const GET_USER_CART = 'GET_USER_CART'; // 用戶購物車數據
export const TOGGLE_SHOP = 'TOGGLE_SHOP'; // 是否選中商品
export const ADD_SHOP = 'ADD_SHOP'; // + 商品
export const SUB_SHOP = 'SUB_SHOP'; // — 商品
export const REMOVE_SHOP = 'REMOVE_SHOP'; // 刪除商品
action.js
import {
SELECT_ALL_SHOP,
GET_USER_CART,
TOGGLE_SHOP,
ADD_SHOP,
SUB_SHOP,
REMOVE_SHOP
} from './visibility';
import { wantShopData } from '../api/shopApi';
// 同步獲取用戶購物車所有數據
export function asyncUserCartData(userCartData){
let cartData = userCartData.map(item => {
item.isSelected = true; // 通過該屬性判斷該條商品是否處於選中狀態
return item;
});
return {
type: GET_USER_CART,
userCartData: cartData
}
}
// 異步獲取用戶購物車數據
export function getUserCarData(userId) {
let statements = `SELECT * FROM userCart WHERE user_id = '${userId}'`;
return (dispatch) => {
wantShopData({ statements }).then(data => {
dispatch(asyncUserCartData(data));
});
}
}
// 購物車選中或不選中
export function checkShopNumber(type, shopId) {
return { type: TOGGLE_SHOP, shopId };
}
// 購物車全選或取消全選
export function operationAllShop(seleStatus) {
return { type: SELECT_ALL_SHOP, seleStatus };
}
// 購物車加商品
export function userAddShop(shopId) {
return { type: ADD_SHOP, shopId }
}
// 購物車減商品
export function userSubShop(shopId) {
return { type: SUB_SHOP, shopId }
}
// 刪除商品
export function removeCartShop(shopId) {
return { type: REMOVE_SHOP, shopId }
}
接下來就是頁面具體實現調用了,在此之前先看下具體是什么樣子的。
一開始購物車的商品都是默認選中的,因為上面的isSelected一開始就是true,現在要實現的就是商品在選中狀態下對於商品數量的變化實現對下面總價的相應變化,注意,首先是只有選中狀態下點擊➕或➖操作下面所有的商品總價會變,而單個商品的總價是不受選中這個狀態影響的,其次要是在未選中狀態下改變單個商品數量,選中后所有商品總價跟着改變,還有就是刪除選中的商品后改變總總價和總數量,最后實現全選和取消全選功能

整個至關重要的一步就是先獲取購物車里的全部數據
首先定義好mapStateToProps和mapDispatchToProps函數,這里使用了react-redux里的connect
import { isLogin, getUserId } from "../../comment/methods/util";
import { getUserCarData } from '../../reduxs/action';
function mapStateToProps(state) {
return {
cartShopData: state.userCartData
};
}
function mapDispatchToProps(dispatch) {
return {
userCartDataFn(userId) {
dispatch(getUserCarData(userId)); // 觸發action
}
}
}
if(isLogin()) { // 判斷登錄后獲取
this.props.userCartDataFn(getUserId());
}esle {
// 沒有登錄即跳往登錄頁
}
// 使用componentWillReceiveProps監測props的變化
// reducers.js
case GET_USER_CART: // 獲取購物車所有數據
return [
...action.userCartData
];
獲取到購物車全部數據后實現單個商品的選中及取消選中、刪除商品
function mapDispatchToProps(dispatch) {
return {
shopTotalFn(type, shopId) { // 商品的選中或取消選中
dispatch(checkShopNumber(type, shopId));
},
removeShop(shopId) { // 刪除商品
dispatch(removeCartShop(shopId));
}
}
}
// 商品的刪除
<!--<Button
type="danger"
onClick={ () => {
this.props.removeShop(this.state.singData.shop_id);
} }>刪除
</Button>-->
// 商品的選中事件selectCheckFn
selectCheckFn() {
this.props.shopTotalFn(TOGGLE_SHOP, this.state.singData.shop_id);
}
// reducers.js
case REMOVE_SHOP: // 移除該商品
let remainShop = state.filter(item => item.shop_id !== action.shopId);
return [ ...remainShop ];
case TOGGLE_SHOP: // 選中或取消選中商品
state.map(item => {
if(action.shopId === item.shop_id) {
item.isSelected = !item.isSelected;
}
});
return [
...state
];
商品數量的加減
這邊得注意商品的選中狀態,選中后改變單總價和總總價,未選中只改變單總價
function mapDispatchToProps(dispatch) {
return {
addShopNum(shopId) {
dispatch(userAddShop(shopId));
},
subShopNum(shopId) {
dispatch(userSubShop(shopId));
}
}
}
reducShopNum() { // 商品減操作
if(this.state.shopNum > 1) {
this.props.subShopNum(this.props.data.shop_id);
this.state.shopNum --;
this.setState({
shopNum: this.state.shopNum
}, () => {
this.props.onChange(this.state.shopNum, this.state.shopPrice);
});
}
}
addShopNum() { // 商品加操作
this.props.addShopNum(this.props.data.shop_id);
this.state.shopNum ++;
this.setState({
shopNum: this.state.shopNum
}, () => {
this.props.onChange(this.state.shopNum, this.state.shopPrice);
});
}
// reducers.js
case ADD_SHOP: // 商品 ++
state.map(item => {
if(item.shop_id === action.shopId) {
item.shop_val ++;
}
});
return [ ...state ];
case SUB_SHOP: // 商品 --
state.map(item => {
if(item.shop_id === action.shopId) {
item.shop_val --;
}
});
return [ ...state ];
最后就是商品的全選和取消全選了
function mapDispatchToProps(dispatch) {
return {
selectStatus(seleStatus) {
dispatch(operationAllShop(seleStatus))
}
}
}
selectAllShop() {
if(this.state.optxt === '全 選') {
this.props.selectStatus('SELECTED_S');
this.setState({
optxt: '取消全選'
});
}else {
this.props.selectStatus('CANCEL_S');
this.setState({
optxt: '全 選'
});
}
}
// reducers.js
case SELECT_ALL_SHOP: // 選中或取消選中所有商品
if(action.seleStatus === 'SELECTED_S') {
state.map(item => {
item.isSelected = true;
});
}
if(action.seleStatus === 'CANCEL_S') {
state.map(item => {
item.isSelected = false;
});
}
return [
...state
];
這樣購物車基本的操作功能也就都實現了,想看完整代碼的可以 點擊一下 進行查看
總結一下:使用了redux后,在購物車操作中確實方便了很多,由於所有的操作都是對一開始的唯一數據源進行操作,從而使思維更加的清晰明確。
