preface
Last semester, I learned vue. js and Node.js in my spare time. I always wanted to do a complete project for practice, but I didn’t have enough time in school before. Now that I have the time, I want to do a project to reinforce what I’ve learned.
I finally decided to imitate Mi Mall to do an e-commerce project, which is almost finished now. This paper summarizes the realization of shopping cart module.
instructions
Complete project repository: github.com/hai-27/vue-… .
The project is deployed on my server, preview link: http://106.15.179.105 (not compatible with mobile terminal, please use PC to access).
This article only summarizes the front-end part, the back-end uses Node.js(Koa)+Mysql implementation, detailed code please go to github.com/hai-27/stor… .
New post, if there is something wrong, please advise more
The effect
No more words, see the effect first
Implementation steps
1. Prepare static pages
The page uses the element-UI Icon, el-checkbox, el-Input-number, el-popover, el-button, all of which need to be introduced in main.js.
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
Copy the code
The page code is as follows:
Note: For convenience, put the final code directly here.
<template>
<div class="shoppingCart">
<! -- Shopping cart header -->
<div class="cart-header">
<div class="cart-header-content">
<p>
<i class="el-icon-shopping-cart-full" style="color:#ff6700; font-weight: 600;">
</i>My shopping cart</p>
<span>Tips: Whether the product is purchased successfully depends on the final order. Please settle as soon as possible</span>
</div>
</div>
<! END -->
<! -- Shopping cart main content area -->
<div class="content" v-if="getShoppingCart.length>0">
<ul>
<! -- Shopping cart header -->
<li class="header">
<div class="pro-check">
<el-checkbox v-model="isAllCheck">select all</el-checkbox>
</div>
<div class="pro-img"></div>
<div class="pro-name">Name of commodity</div>
<div class="pro-price">The unit price</div>
<div class="pro-num">The number of</div>
<div class="pro-total">subtotal</div>
<div class="pro-action">operation</div>
</li>
<! END -->
<! -- Shopping cart list -->
<li class="product-list" v-for="(item,index) in getShoppingCart" :key="item.id">
<div class="pro-check">
<el-checkbox :value="item.check" @change="checkChange($event,index)">
</el-checkbox>
</div>
<div class="pro-img">
<router-link :to="{ path: '/goods/details', query: {productID:item.productID} }">
<img :src="$target + item.productImg" />
</router-link>
</div>
<div class="pro-name">
<router-link
:to="{ path: '/goods/details', query: {productID:item.productID} }"
>{{item.productName}}</router-link>
</div>
<div class="pro-price">{{item. Price}}</div>
<div class="pro-num">
<el-input-number
size="small"
:value="item.num"
@change="handleChange($event,index,item.productID)"
:min="1"
:max="item.maxNum"
></el-input-number>
</div>
<div class="pro-total pro-total-in">{{item. The item price *. Num}}</div>
<div class="pro-action">
<el-popover placement="right">
<p>Are you sure?</p>
<div style="text-align: right; margin: 10px 0 0">
<el-button
type="primary"
size="mini"
@click="deleteItem($event,item.id,item.productID)"
>determine</el-button>
</div>
<i class="el-icon-error" slot="reference" style="font-size: 18px;"></i>
</el-popover>
</div>
</li>
<! END -->
</ul>
<div style="height:20px; background-color: #f5f5f5"></div>
<! -- Shopping cart bottom navigation bar -->
<div class="cart-bar">
<div class="cart-bar-left">
<span>
<router-link to="/goods">To continue shopping</router-link>
</span>
<span class="sep">|</span>
<span class="cart-total">
共
<span class="cart-total-num">{{getNum}}</span>Item, selected<span class="cart-total-num">{{getCheckNum}}</span> 件
</span>
</div>
<div class="cart-bar-right">
<span>
<span class="total-price-title">Total:</span>
<span class="total-price">{{getTotalPrice}}</span>
</span>
<router-link :to="getCheckNum > 0 ? '/confirmOrder' : ''">
<div :class="getCheckNum > 0 ? 'btn-primary' : 'btn-primary-disabled'">To settle accounts</div>
</router-link>
</div>
</div>
<! -- Shopping cart navigation bar END -->
</div>
<! -- Shopping cart main contents END -->
<! -- What to display when shopping cart is empty -->
<div v-else class="cart-empty">
<div class="empty">
<h2>Your shopping cart is still empty!</h2>
<p>Go shopping!</p>
</div>
</div>
<! -- What to display when shopping cart is empty
</div>
</template>
Copy the code
2. Create Vuex
/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import shoppingCart from './modules/shoppingCart'
Vue.use(Vuex)
export default new Vuex.Store({
strict: true.modules: {
shoppingCart
}
})
Copy the code
/store/modules/shoppingCart.js
export default {
state: {
shoppingCart: []
/ / shoppingCart structure
/* shoppingCart = {id: "", // shoppingCart = {id: "", // shoppingCart = {id: "", // shoppingCart = {id: "", // shoppingCart = {id: "", // "Num: / / commodity prices", "", / / quantity maxNum:" ", / / commodity purchase quantity check: check whether false / /} * /}}Copy the code
3. Synchronize shopping cart status
Ideas:
- Monitor user login status in the root component app.vue;
- If the user is logged in, retrieve the user’s shopping cart data from the database and update the obtained data to VUEX;
- The user is not logged in. Set the status of the shopping cart in VUEX to empty.
The code is as follows:
import { mapActions } from "vuex";
import { mapGetters } from "vuex"; computed: { ... mapGetters(["getUser"."getNum"])},methods: {
...mapActions(["setShoppingCart"]),
}
watch: {
// Obtain the vuEX login status
getUser: function(val) {
if (val === "") {
// The user is not logged in
this.setShoppingCart([]);
} else {
// The user has logged in to get the shopping cart information for the user
this.$axios
.post("/api/user/shoppingCart/getShoppingCart", {
user_id: val.user_id
})
.then(res= > {
if (res.data.code === "001") {
// 001 To succeed, update vuex shopping cart status
this.setShoppingCart(res.data.shoppingCartData);
} else {
// A failure message is displayed
this.notifyError(res.data.msg);
}
})
.catch(err= > {
return Promise.reject(err); }); }}}Copy the code
Vuex mutations:
setShoppingCart (state, data) {
// Set the shopping cart state
state.shoppingCart = data;
},
Copy the code
The actions of vuex
setShoppingCart({ commit }, data) {
commit('setShoppingCart', data);
}
Copy the code
4. Dynamically generate shopping cart pages
Ideas:
- Getters. GetShoppingCart in VUEX to get the status of shopping cart;
- Use V-if to determine whether the shopping cart has items;
- If present, use V-for to generate a shopping cart list;
- If it does not exist, display what was displayed when the shopping cart was empty;
Shopping cart HTML pseudocode:
<div class="shoppingCart">
<div class="content" v-if="getShoppingCart.length>0">
<ul>
<li class="header">
<! -- Shopping cart header, omit detail code -->
</li>
<li class="product-list" v-for="(item,index) in getShoppingCart" :key="item.id">
<! -- Shopping cart list section, omit detailed code -->
</li>
</ul>
</div>
<! -- What to display when shopping cart is empty -->
<div v-else class="cart-empty">
<div class="empty">
<h2>Your shopping cart is still empty!</h2>
<p>Go shopping!</p>
</div>
</div>
</div>
Copy the code
Vuex getters:
getShoppingCart(state) {
// Get the cart status
return state.shoppingCart;
}
Copy the code
5. Add items to cart
Ideas:
- The user in the product details page, by clicking the add cart button, call click event addShoppingCart;
- First initiate a request to add shopping cart to the back end, and operate VUEX according to the returned information;
- The first time the item is added to the cart, the cart information returned by the back end is inserted into vuex through vuex’s Actions (unshiftShoppingCart);
- The item is already in the shopping cart, add the item quantity +1 by vuex’s Actions (addShoppingCartNum);
- Do not click add to cart button when the quantity of goods reaches the limit.
HTML:
<el-button class="shop-cart" :disabled="dis" @click="addShoppingCart">Add to shopping cart</el-button>
Copy the code
The logical code is as follows:
methods: { ... mapActions(["unshiftShoppingCart"."addShoppingCartNum"]),
// Add to cart
addShoppingCart() {
// Check whether you are logged in. If you are not logged in, the login component is displayed
if (!this.$store.getters.getUser) {
this.$store.dispatch("setShowLogin".true);
return;
}
// The back end makes a request to insert the item information into the shopping cart table of the database
this.$axios
.post("/api/user/shoppingCart/addShoppingCart", {
user_id: this.$store.getters.getUser.user_id,
product_id: this.productID
})
.then(res= > {
switch (res.data.code) {
case "001":
// Added to shopping cart successfully
this.unshiftShoppingCart(res.data.shoppingCartData[0]);
this.notifySucceed(res.data.msg);
break;
case "002":
// The item is already in the cart, quantity +1
this.addShoppingCartNum(this.productID);
this.notifySucceed(res.data.msg);
break;
case "003":
// The quantity reaches the limit
this.dis = true;
this.notifyError(res.data.msg);
break;
case "401":
// No login
this.$store.dispatch("setShowLogin".true);
this.notifyError(res.data.msg);
break;
default:
this.notifyError(res.data.msg);
}
})
.catch(err= > {
return Promise.reject(err); }); }}Copy the code
Vuex mutations:
unshiftShoppingCart(state, data) {
// Add items to cart
// It is used to click Add shopping cart on the product details page, and update vuEX status after the background is added successfully
state.shoppingCart.unshift(data);
},
addShoppingCartNum(state, productID) {
// Add items to cart
// It is used to click add shopping cart on the product details page, and the background returns 002, "The product has been in the shopping cart, quantity +1" to update the quantity of vuex goods
for (let i = 0; i < state.shoppingCart.length; i++) {
const temp = state.shoppingCart[i];
if (temp.productID == productID) {
if(temp.num < temp.maxNum) { temp.num++; }}}}Copy the code
Vuex actions:
unshiftShoppingCart({ commit }, data) {
commit('unshiftShoppingCart', data);
},
addShoppingCartNum({ commit }, productID) {
commit('addShoppingCartNum', productID);
}
Copy the code
6. Delete items from your cart
Ideas:
- Each item in the shopping cart has a delete button. If the user clicks the delete button, the confirmation dialog box will pop up first.
- When the user selects confirm delete, call the click event called deleteItem ($event, the item id, item. The productID);
- Click the event to get the shopping cart ID and commodity ID;
- First, initiate a request to delete the shopping cart from the back end, and operate VUEX according to the returned information;
- Delete the item from the cart by vuex’s Actions (deleteShoppingCart).
- If the deletion fails, a message is displayed.
HTML:
<div class="pro-action">
<el-popover placement="right">
<p>Are you sure?</p>
<div style="text-align: right; margin: 10px 0 0">
<el-button type="primary" size="mini"
@click="deleteItem($event,item.id,item.productID)">determine</el-button>
</div>
<i class="el-icon-error" slot="reference" style="font-size: 18px;"></i>
</el-popover>
</div>
Copy the code
The logical code is as follows:
methods: {
// The backend initiates a database information request to delete the shopping cart
deleteItem(e, id, productID) {
this.$axios
.post("/api/user/shoppingCart/deleteShoppingCart", {
user_id: this.$store.getters.getUser.user_id,
product_id: productID
})
.then(res= > {
switch (res.data.code) {
case "001":
// The deletion succeeded
// Update the vuEX status
this.deleteShoppingCart(id);
// The deletion success message is displayed
this.notifySucceed(res.data.msg);
break;
default:
// A deletion failure message is displayed
this.notifyError(res.data.msg);
}
})
.catch(err= > {
return Promise.reject(err); }); }}Copy the code
Vuex mutations:
deleteShoppingCart(state, id) {
// Delete the cart item according to the cart ID
for (let i = 0; i < state.shoppingCart.length; i++) {
const temp = state.shoppingCart[i];
if (temp.id == id) {
state.shoppingCart.splice(i, 1); }}}Copy the code
Vuex actions:
deleteShoppingCart({ commit }, id) {
commit('deleteShoppingCart', id);
}
Copy the code
7. Modify the number of items in your cart
Ideas:
- Each item in the cart has a counter, which can be modified by clicking the plus or minus button, or by directly entering the number of items in the input box. The counter is usedelement-ui 的
el-input-number
The implementation. - The change event of the counter gets the new quantity, the index of the shopping cart item (that is, the index of the array), and the item ID.
- First, initiate a request to modify the number of items in the shopping cart at the back end, and operate vuEX according to the returned information;
- Vuex Actions (updateShoppingCart) to change the number of items in the shopping cart.
- Failure message is displayed. Among them: the quantity is less than 1, whether the quantity reaches the purchase limit (in these two cases, there is a front set check, generally will not appear).
HTML:
<div class="pro-num">
<el-input-number
size="small"
:value="item.num"
@change="handleChange($event,index,item.productID)"
:min="1"
:max="item.maxNum"
>
</el-input-number>
Copy the code
The logical code is as follows:
// This function is called when the number of items is changed
handleChange(currentValue, key, productID) {
// This parameter is selected by default when changing the number
this.updateShoppingCart({ key: key, prop: "check".val: true });
// The back end initiates a request to modify the number of items in the cart
this.$axios
.post("/api/user/shoppingCart/updateShoppingCart", {
user_id: this.$store.getters.getUser.user_id,
product_id: productID,
num: currentValue
})
.then(res= > {
switch (res.data.code) {
case "001":
// 001 indicates that the modification is successful
// Update the vuEX status
this.updateShoppingCart({
key: key,
prop: "num".val: currentValue
});
// A message is displayed indicating that the modification is successful
this.notifySucceed(res.data.msg);
break;
default:
// Failure message is displayed
this.notifyError(res.data.msg);
}
})
.catch(err= > {
return Promise.reject(err);
});
}
Copy the code
Vuex mutations:
updateShoppingCart(state, payload) {
// Update the shopping cart
// The number of items can be updated and whether to check
// For shopping cart click tick and add or subtract item quantity
if (payload.prop == "num") {
// Determine whether the number of goods is greater than the limit or less than 1
if (state.shoppingCart[payload.key].maxNum < payload.val) {
return;
}
if (payload.val < 1) {
return; }}// Changes based on the index and properties of the items in the shopping cart array
state.shoppingCart[payload.key][payload.prop] = payload.val;
}
Copy the code
Vuex actions:
updateShoppingCart({ commit }, payload) {
commit('updateShoppingCart', payload);
}
Copy the code
8. Check whether to select goods
Ideas:
- Shopping cart each item has a check box, useelement-ui 的
el-checkbox
Implementation, the settlement of all ticked goods submitted. - Get the check box state (true or false) and the index of the shopping cart items (that is, the index of the array) through the change event.
- Vuex Actions (updateShoppingCart) to change the checkbox status of shopping cart items.
html:
<div class="pro-check">
<el-checkbox :value="item.check" @change="checkChange($event,index)"></el-checkbox>
</div>
Copy the code
The logical code is as follows:
checkChange(val, key) {
// Update the status of whether shopping cart items are checked in vuex
this.updateShoppingCart({ key: key, prop: "check".val: val });
}
Copy the code
Note: The vuex mutationSvuex and Actions used here are the same as those for modifying the quantity of goods. They are distinguished by different parameters passed. {key: key, prop: “num”, val: val} are the parameters for changing the number of goods. Whether to select {key: key, prop: “check”, val: val} are the parameters for changing the number of goods.
9. Whether to select all products
Ideas:
- The shopping cart is set up with a full checkbox, bound to isAllCheck via v-Model.
- The isAllCheck value is getters. GetIsAllCheck in vuex by calculating the getter of the property.
- Getters. GetIsAllCheck in vuex judges the checked status of each item by traversing the shopping cart array. As long as one item is not checked, getIsAllCheck is false, otherwise it is true.
- When clicking on the checkAll box, vuex’s Actions (checkAll) are called through the setter of the calculated property to change the checkAll status of each item, thus changing the checkAll status of the checkAll box.
HTML:
<div class="pro-check">
<el-checkbox v-model="isAllCheck">select all</el-checkbox>
</div>
Copy the code
The logical code is as follows:
computed: {
isAllCheck: {
get() {
return this.$store.getters.getIsAllCheck;
},
set(val) {
this.checkAll(val); }}}Copy the code
Vuex getters:
getIsAllCheck(state) {
// Check whether all are selected
let isAllCheck = true;
for (let i = 0; i < state.shoppingCart.length; i++) {
const temp = state.shoppingCart[i];
// Return immediately if one item is not checked false;
if(! temp.check) { isAllCheck =false;
returnisAllCheck; }}return isAllCheck;
}
Copy the code
Vuex mutations:
checkAll(state, data) {
// Click the all button to change the check status of each item
for (let i = 0; i < state.shoppingCart.length; i++) { state.shoppingCart[i].check = data; }}Copy the code
The actions of vuex
checkAll({ commit }, data) {
commit('checkAll', data);
}
Copy the code
10. Count the total number of items in your cart
Used in the shopping cart page and the top navigation bar of the root component.
Vuex getters:
getNum(state) {
// Total number of items in cart
let totalNum = 0;
for (let i = 0; i < state.shoppingCart.length; i++) {
const temp = state.shoppingCart[i];
totalNum += temp.num;
}
return totalNum;
}
Copy the code
11. Count the total number of items checked in your shopping cart
Used on the shopping cart page and billing page.
Vuex getters:
getCheckNum(state) {
// Get the total number of items checked in the shopping cart
let totalNum = 0;
for (let i = 0; i < state.shoppingCart.length; i++) {
const temp = state.shoppingCart[i];
if(temp.check) { totalNum += temp.num; }}return totalNum;
}
Copy the code
12. Calculate the total price of items checked in the shopping cart
Used on the shopping cart page and billing page.
Vuex getters:
getTotalPrice(state) {
// Total price of items checked by shopping cart
let totalPrice = 0;
for (let i = 0; i < state.shoppingCart.length; i++) {
const temp = state.shoppingCart[i];
if(temp.check) { totalPrice += temp.price * temp.num; }}return totalPrice;
}
Copy the code
13. Generate the details of items checked in the shopping cart
Used on the settlement page.
Vuex getters:
getCheckGoods(state) {
// Get the checked item information
// To confirm the order page
let checkGoods = [];
for (let i = 0; i < state.shoppingCart.length; i++) {
const temp = state.shoppingCart[i];
if(temp.check) { checkGoods.push(temp); }}return checkGoods;
}
Copy the code
conclusion
At this point, the front end of the shopping cart is fully implemented: Synchronous shopping cart data from a database, according to the shopping cart data dynamically generated a shopping cart page, add items to shopping cart, remove the items in the cart, modify the number of shopping cart of goods, whether to check the shopping cart of goods, whether all shopping cart items, calculate the total amount of goods in the shopping cart, and calculate the total number of items in the shopping cart checked, Calculate the total price of the items checked in the shopping cart and generate the details of the items checked in the shopping cart.
Afterword.
The end, the first post of the new person, if there is something wrong, please advise more ^_^
This article is based on the complete project, the implementation of the shopping cart module is summarized.
Complete project repository: github.com/hai-27/vue-… .
Project preview link: http://106.15.179.105 (not compatible with mobile terminals, please use PC access).
If you like this article, please give it a “like”, if you can add a Star to the complete project repository, thank you ^_^
There will be more summaries of this project, and those who are interested can click on it.
Thanks for reading!
The author hai – 27
8 March 2020