需求分析:
列表頁list.html
html結(jié)構(gòu)
<p class="login-txt">登錄</p>
<p> <a href="register.html">注冊</a></p>
<p><a href="./shopCart.html">購物車</a></p>
<div id="box">
<ul>
</ul>
</div>
<div class="mask">
<div class="login">
<p><input type="text" class="user"/></p>
<p><input type="text" class="pw"/></p>
<p><button>登錄</button>></p>
</div>
</div>
<script src="js/axios.js"></script>
<script src="js/jquery.js"></script>
<script src="js/jquery.cookie.js"></script>
<script src="js/list.js"></script>
<script src="js/addCart.js"></script>
<script src="js/login.js"></script>
列表頁功能一: 初始化展示商品列表
前端代碼
let page = 1; //頁碼
let mask = document.querySelector(".mask") //獲取dom
// 渲染數(shù)據(jù)
function render(data) {
if (data.code === 0) {
let html = ''
data.list.forEach((item) => {
html += `
<li>
<a href="./detail.html?id=${item.Id}">
<div class="pro_img"><img src="https:${item.imgUrl}" width="150" height="150"></div>
<h3 class="pro_name"><a href="#"> ${item.title} </a></h3>
<p class="pro_price">${item.price}元</p>
<p></p>
<div class="add_btn" data-id="${item.Id}">加入購物車</div>
</a>
</li>
`
})
$("#box ul").append(html)
}
}
// 初始化加載數(shù)據(jù)
function initData() {
axios.get("/product",{
params: {
page
}
})
.then((res) => {
render(res.data)
})
}
initData()
后端代碼
// 查詢所有商品(分頁顯示)
router.get("/product", (req, res) => {
let { page } = req.query;
const pageSize = 10;
let start = (page - 1) * pageSize
let sql = `select * from midata order by Id asc limit ?,?`
conn.query(sql, [start, pageSize], function (err, result) {
if (err) {
console.log('查詢數(shù)據(jù)庫失敗');
} else {
let data;
if (result.length) {
data = {
code: 0,
list: result
}
} else {
data = {
code: 1,
msg: '沒有結(jié)果 '
}
}
res.send(data)
}
})
})
列表頁功能二: 登錄入口酱虎,可在本頁面顯示登錄窗口咖杂,實現(xiàn)登錄功能
// 每個頁面中的登錄
function login() {
$(".mask button").on("click", function () {
let data = {
user: $(".user").val(),
pw: $(".pw").val()
}
axios.post('/login', data)
.then((res) => {
console.log(res.data);
mask.classList.remove("active")
$.cookie("user",data.user,{ expires: 100})
})
})
}
//登錄彈窗
function loginBox() {
let loginTxt = document.querySelector(".login-txt")
var login = document.querySelector(".login")
//綁定事件啦撮,單擊登錄時谁撼,顯示彈窗
loginTxt.onclick = function () {
mask.classList.add("active")
}
//單擊遮罩層砂沛,讓遮罩層消失
mask.onclick = function () {
this.classList.remove("active")
}
//阻止冒泡
login.onclick = function (e) {
e.stopPropagation()
}
}
login()
loginBox()
列表頁功能三: 每個商品實現(xiàn)加入購物車功能
先驗證是否登錄,如何沒有登錄哀澈,進(jìn)行登錄牌借,如果已登錄,則把商品id和用戶id傳向后端接口
前端代碼
function cart() {
// 加入購物車
function addCart() {
$("#box ul").on("click", ".add_btn", function () {
//驗證用戶是否登錄
let userId = $.cookie("user");
let proId = $(this).data("id") //獲取商品Id
console.log(proId);
if (!userId) {
//當(dāng)cookie不存在割按,即沒有登錄
mask.classList.add("active")
return;
}
let data = {
userId,
proId
}
axios.post("/cart",data)
.then((res)=>{
console.log(res.data);
})
})
}
addCart();
}
cart()
后端代碼
// 添加商品到購物車
router.post("/cart", (req, res) => {
//接收參數(shù)
let { userId, proId } = req.body;
let sql = "select * from cart where userId = ? and proId = ?"
conn.query(sql, [userId, proId], function (err, result) {
if (err) {
console.log('數(shù)據(jù)庫訪問失敗');
} else {
let data;
if (result.length) {
console.log('11');
//當(dāng)前用戶存在該商品
let cartId = result[0].cartId
let num = result[0].num + 1
// 更新商品數(shù)量
let sql = "update cart set num = ? where cartId = ?"
conn.query(sql, [num, cartId], function (err, result) {
if (result.affectedRows === 1) {
res.send({
code: 0,
msg: '添加購物車成功膨报,數(shù)量更改'
})
}
})
} else {
console.log(22);
//當(dāng)前用戶不存在該商品
let sql = "insert into cart (userId,proId,num) values (?,?,?)"
conn.query(sql, [userId, proId, 1], function (err, result) {
if (result.affectedRows === 1) {
res.send({
code: 0,
msg: '添加購物車成功,數(shù)量初始為1'
})
}
})
}
}
})
})
列表頁功能四: 加入購物車
后端接口接收商品id和用戶id适荣,先驗證該用戶的當(dāng)前商品是否存在现柠,如果不存在,則新增弛矛,如果存在够吩,則修改數(shù)量
前端代碼
function cart() {
// 加入購物車
function addCart() {
$("#box ul").on("click", ".add_btn", function () {
//驗證用戶是否登錄
let userId = $.cookie("user");
let proId = $(this).data("id") //獲取商品Id
console.log(proId);
if (!userId) {
//當(dāng)cookie不存在,即沒有登錄
mask.classList.add("active")
return;
}
let data = {
userId,
proId
}
axios.post("/cart",data)
.then((res)=>{
console.log(res.data);
})
})
}
addCart();
}
cart()
后端代碼
// 添加商品到購物車
router.post("/cart", (req, res) => {
//接收參數(shù)
let { userId, proId } = req.body;
let sql = "select * from cart where userId = ? and proId = ?"
conn.query(sql, [userId, proId], function (err, result) {
if (err) {
console.log('數(shù)據(jù)庫訪問失敗');
} else {
let data;
if (result.length) {
console.log('11');
//當(dāng)前用戶存在該商品
let cartId = result[0].cartId
let num = result[0].num + 1
// 更新商品數(shù)量
let sql = "update cart set num = ? where cartId = ?"
conn.query(sql, [num, cartId], function (err, result) {
if (result.affectedRows === 1) {
res.send({
code: 0,
msg: '添加購物車成功丈氓,數(shù)量更改'
})
}
})
} else {
console.log(22);
//當(dāng)前用戶不存在該商品
let sql = "insert into cart (userId,proId,num) values (?,?,?)"
conn.query(sql, [userId, proId, 1], function (err, result) {
if (result.affectedRows === 1) {
res.send({
code: 0,
msg: '添加購物車成功周循,數(shù)量初始為1'
})
}
})
}
}
})
})
列表頁功能五: 跳轉(zhuǎn)至詳情頁
單擊商品,跳轉(zhuǎn)到詳情頁万俗,并傳遞當(dāng)前商品id
前端代碼
<a href="./detail.html?id=${item.Id}">商品</a>
詳情頁: detail.html
詳情頁功能一: 初始化獲取商品id, 請求后端接口湾笛,獲取商品信息并渲染
前端代碼
// 獲取Id
function getId(){
let search = location.search; // "?id=100"
let result = search.match(/^\?id=(\d+)$/)
let id = result[1];
return id
}
//渲染數(shù)據(jù)
function render(res){
if (res.data.code === 0) {
let item = res.data.list[0]
let html = ''
html += `
<li>
<a href="./detail.html?id=${item.Id}">
<div class="pro_img"><img src="https:${item.imgUrl}" width="150" height="150"></div>
<h3 class="pro_name"><a href="#"> ${item.title} </a></h3>
<p class="pro_price">${item.hot}元</p>
<div class="add_btn" data-id="${item.Id}">加入購物車</div>
</a>
</li>
`
$("#box ul").append(html)
}
}
//獲取指定id對應(yīng)的商品信息
function getProduct() {
let id = getId()
axios.get(`/product/${id}`)
.then((res) => {
render(res)
})
}
getProduct()
后端代碼
router.get("/product/:id", (req, res) => {
let { id } = req.params;
let sql = `select * from midata where id = ?`
conn.query(sql, [id], function (err, result) {
if (err) {
console.log('查詢數(shù)據(jù)庫失敗');
} else {
let data;
if (result.length) {
data = {
code: 0,
list: result
}
} else {
data = {
code: 1,
msg: '沒有結(jié)果 '
}
}
res.send(data)
}
})
})
詳情頁功能二: 加入購物車功能,邏輯參考列表頁功能
購物車 shopCart.html
購物車功能一: 初始化請求后臺接口闰歪,并傳遞當(dāng)前用戶id, 請求該用戶的所有購物信息并展示
前端代碼
// 查看用戶是否登錄
function checkIsLogin(userId) {
if (!userId) return;
//登錄過
$("h1").addClass("hide")
$(".car").removeClass("hide")
}
//渲染數(shù)據(jù)
function render(res) {
if (res.data.code == 0) {
let html = ""
res.data.list.forEach((item) => {
html += `
<div class="row hid">
<div class="check left"> <input type="checkbox" class="select"></div>
<div class="img left"><img src="img/03-car-02.png" width="80" height="80"></div>
<div class="name left"><span> ${item.title} </span></div>
<div class="price left"><span>${item.price}元</span></div>
<div class="item_count_i">
<div class="num_count">
<div class="count_d" data-id="${item.cartId}">-</div>
<div class="c_num">${item.num}</div>
<div class="count_i" data-id="${item.cartId}">+</div>
</div>
</div>
<div class="subtotal left"><span>${item.price * item.num}元</span></div>
<div class="ctrl left"><a href="javascript:;" data-id="${item.cartId}">×</a></div>
</div>
`
})
$(".list").html(html)
}
}
// 請求購物車列表數(shù)據(jù)
function loadData() {
let userId = $.cookie("user")
checkIsLogin(userId)
// 請求數(shù)據(jù)
axios.get("/cart", {
params: {
userId
}
})
.then((res) => {
render(res)
})
}
后端代碼
//查詢購物車信息
router.get("/cart", (req, res) => {
let { userId } = req.query;
let sql = `select * from cart,midata where cart.userId = ? and cart.proId = midata.Id order by cart.cartId desc`
conn.query(sql, [userId], function (err, result) {
if (err) {
console.log('查詢數(shù)據(jù)庫失敗');
} else {
let data;
if (result.length) {
data = {
code: 0,
list: result
}
} else {
data = {
code: 1,
msg: '沒有結(jié)果 '
}
}
res.send(data)
}
})
})
購物車功能二: 復(fù)選框全選的單擊事件: 選中時嚎研,所有商品也要選中,取消選擇時库倘,所有商品也取消選擇. 同時計算總價
計算總價
let total = 0; //總價
//計算總價
function getTotal() {
total = 0;
[...$(".list .select")].forEach((item) => {
if ($(item).prop("checked")) {
let subTotal = parseFloat($(item).parent().parent().find(".subtotal span").text())
total += subTotal
}
})
$("#sum_area #price_num").text(total)
}
前端代碼
// 全選功能
function checkAll() {
$(".check-all").on("click", function () {
let selected = $(this).prop("checked")
$(".list .select").prop("checked", selected)
getTotal()
})
}
購物車功能三. 每個商品復(fù)選框的單擊事件: 單擊時临扮,要遍歷所有商品的選中狀態(tài)论矾,都被選中,則選中“全選”復(fù)選框杆勇,都取消選中拇囊,則取消“全選”復(fù)選框。 同時計算總價
前端代碼
//切換某一個商品的選擇狀態(tài)
function toggleOne() {
$(".list").on("click", ".select", function () {
let selected = $(this).prop("checked")
if (selected) {
let flag = [...$(".list .select")].every((item) => {
return $(item).prop("checked")
})
if (flag) {
$(".check-all").prop("checked", true)
}
} else {
$(".check-all").prop("checked", false)
}
getTotal()
})
}
購物車功能四. 加減數(shù)量: 獲取原有數(shù)量靶橱,加或減后寥袭,調(diào)用后端接口,傳遞數(shù)量关霸,CartId, 后端則把對應(yīng)購物車信息的數(shù)量進(jìn)行更新传黄。 前端接收到更新成功后,計算小計價格队寇,并同時計算總價
前端代碼
//改變數(shù)量
function changeNum(el, type) {
$(".list").on("click", el, function () {
let num = $(this).siblings(".c_num").text()
type === 'add' ? num++ : num--
//后端接口
let data = {
cartId: $(this).data("id"),
num
}
axios.put("/cart", data)
.then((res) => {
//前端
$(this).parent().parent().siblings(".check").children(".select").prop("checked", true);
let price = parseFloat($(this).parent().parent().siblings(".price").children("span").text())
$(this).siblings(".c_num").text(num)
let subTotal = num * price
$(this).parent().parent().siblings(".subtotal").children("span").text(subTotal)
getTotal()
})
})
}
后端代碼
//修改商品數(shù)量
router.put("/cart", (req, res) => {
//接收參數(shù)
let { cartId, num } = req.body;
let sql = "update cart set num = ? where cartId = ?"
conn.query(sql, [num, cartId], function (err, result) {
if (err) {
console.log('數(shù)據(jù)庫訪問失敗');
} else {
if (result.affectedRows === 1) {
res.send({
code: 0,
msg: '添加購物車成功膘掰,數(shù)量更改'
})
}
}
})
})
購物車功能五: 刪除: 調(diào)用后端接口,傳遞CartId, 在后端刪除指定CartId的信息佳遣,前端接收到成功刪除后识埋,再次到后端請求當(dāng)前用戶所有購物車信息并渲染
前端代碼
// 刪除購物車信息
function delCart() {
$(".list").on("click", ".ctrl a", function () {
let cartId = $(this).data("id")
axios.delete(`/cart/${cartId}`)
.then((res) => {
loadData()
})
})
}
后端代碼
//刪除購物車信息
router.delete("/cart/:cartId", (req, res) => {
let { cartId } = req.params;
let sql = `delete from cart where cartId = ?`
conn.query(sql, [cartId], function (err, result) {
if (err) {
console.log('查詢數(shù)據(jù)庫失敗');
} else {
let data;
if (result.affectedRows === 1) {
data = {
code: 0,
msg: '刪除成功'
}
}
res.send(data)
}
})
})