结构:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>我的购物车-品优购</title>
<meta name="description"
content="品优购JD.COM-专业的综合网上购物商城,销售家电、数码通讯、电脑、家居百货、服装服饰、母婴、图书、食品等数万个品牌优质商品.便捷、诚信的服务,为您提供愉悦的网上购物体验!" />
<meta name="Keywords" content="网上购物,网上商城,手机,笔记本,电脑,MP3,CD,VCD,DV,相机,数码,配件,手表,存储卡,品优购" />
<!-- 引入facicon.ico网页图标 -->
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<!-- 引入css 初始化的css 文件 -->
<link rel="stylesheet" href="css/base.css">
<!-- 引入公共样式的css 文件 -->
<link rel="stylesheet" href="css/common.css">
<!-- 引入car css -->
<link rel="stylesheet" href="css/car.css">
<!-- 先引入jquery -->
<script src="js/jquery.min.js"></script>
<!-- 引入vue.js -->
<script src="js/vue.min.js"></script>
<!-- 在引入我们自己的js文件 -->
<!-- <script src="js/car.js"></script> -->
<script src='js/vue_mycart.js'></script>
<!-- 引入axios -->
<script src='js/axios.min.js'></script>
<script type ='text/javascript' >
</script>
</head>
<body>
<!-- 顶部快捷导航start -->
<div class="shortcut">
<div class="w">
<div class="fl">
<ul>
<li>品优购欢迎您! </li>
<li>
<a href="#">请登录</a>
<a href="#" class="style-red">免费注册</a>
</li>
</ul>
</div>
<div class="fr">
<ul>
<li><a href="#">我的订单</a></li>
<li class="spacer"></li>
<li>
<a href="#">我的品优购</a>
<i class="icomoon"></i>
</li>
<li class="spacer"></li>
<li><a href="#">品优购会员</a></li>
<li class="spacer"></li>
<li><a href="#">企业采购</a></li>
<li class="spacer"></li>
<li><a href="#">关注品优购</a> <i class="icomoon"></i></li>
<li class="spacer"></li>
<li><a href="#">客户服务</a> <i class="icomoon"></i></li>
<li class="spacer"></li>
<li><a href="#">网站导航</a> <i class="icomoon"></i></li>
</ul>
</div>
</div>
</div>
<!-- 顶部快捷导航end -->
<div class="car-header">
<div class="w">
<div class="car-logo">
<img src="img/logo.png" alt=""> <b>购物车</b>
</div>
</div>
</div>
<!-- </div> -->
<div class="c-container">
<div class="w">
<div class="cart-filter-bar">
<em>全部商品</em>
</div>
<!-- 购物车主要核心区域 -->
<div class="cart-warp">
<div id="app">
<my-cart></my-cart>
</div>
<!-- 头部全选模块 -->
<!-- 商品详细模块 -->
<!-- 结算模块 -->
</div>
</div>
</div>
<!-- footer start -->
<div class="footer">
<div class="w">
<!-- mod_service -->
<div class="mod_service">
<ul>
<li>
<i class="mod-service-icon mod_service_zheng"></i>
<div class="mod_service_tit">
<h5>正品保障</h5>
<p>正品保障,提供发票</p>
</div>
</li>
<li>
<i class="mod-service-icon mod_service_kuai"></i>
<div class="mod_service_tit">
<h5>正品保障</h5>
<p>正品保障,提供发票</p>
</div>
</li>
<li>
<i class="mod-service-icon mod_service_bao"></i>
<div class="mod_service_tit">
<h5>正品保障</h5>
<p>正品保障,提供发票</p>
</div>
</li>
<li>
<i class="mod-service-icon mod_service_bao"></i>
<div class="mod_service_tit">
<h5>正品保障</h5>
<p>正品保障,提供发票</p>
</div>
</li>
<li>
<i class="mod-service-icon mod_service_bao"></i>
<div class="mod_service_tit">
<h5>正品保障</h5>
<p>正品保障,提供发票</p>
</div>
</li>
</ul>
</div>
<!-- mod_help -->
<div class="mod_help">
<dl class="mod_help_item">
<dt>购物指南</dt>
<dd> <a href="#">购物流程 </a></dd>
<dd> <a href="#">会员介绍 </a></dd>
<dd> <a href="#">生活旅行/团购 </a></dd>
<dd> <a href="#">常见问题 </a></dd>
<dd> <a href="#">大家电 </a></dd>
<dd> <a href="#">联系客服 </a></dd>
</dl>
<dl class="mod_help_item">
<dt>购物指南</dt>
<dd> <a href="#">购物流程 </a></dd>
<dd> <a href="#">会员介绍 </a></dd>
<dd> <a href="#">生活旅行/团购 </a></dd>
<dd> <a href="#">常见问题 </a></dd>
<dd> <a href="#">大家电 </a></dd>
<dd> <a href="#">联系客服 </a></dd>
</dl>
<dl class="mod_help_item">
<dt>购物指南</dt>
<dd> <a href="#">购物流程 </a></dd>
<dd> <a href="#">会员介绍 </a></dd>
<dd> <a href="#">生活旅行/团购 </a></dd>
<dd> <a href="#">常见问题 </a></dd>
<dd> <a href="#">大家电 </a></dd>
<dd> <a href="#">联系客服 </a></dd>
</dl>
<dl class="mod_help_item">
<dt>购物指南</dt>
<dd> <a href="#">购物流程 </a></dd>
<dd> <a href="#">会员介绍 </a></dd>
<dd> <a href="#">生活旅行/团购 </a></dd>
<dd> <a href="#">常见问题 </a></dd>
<dd> <a href="#">大家电 </a></dd>
<dd> <a href="#">联系客服 </a></dd>
</dl>
<dl class="mod_help_item">
<dt>购物指南</dt>
<dd> <a href="#">购物流程 </a></dd>
<dd> <a href="#">会员介绍 </a></dd>
<dd> <a href="#">生活旅行/团购 </a></dd>
<dd> <a href="#">常见问题 </a></dd>
<dd> <a href="#">大家电 </a></dd>
<dd> <a href="#">联系客服 </a></dd>
</dl>
<dl class="mod_help_item mod_help_app">
<dt>帮助中心</dt>
<dd>
<img src="upload/erweima.png" alt="">
<p>品优购客户端</p>
</dd>
</dl>
</div>
<!-- mod_copyright -->
<div class="mod_copyright">
<p class="mod_copyright_links">
关于我们 | 联系我们 | 联系客服 | 商家入驻 | 营销中心 | 手机品优购 | 友情链接 | 销售联盟 | 品优购社区 | 品优购公益 | English Site | Contact U
</p>
<p class="mod_copyright_info">
地址:北京市昌平区建材城西路金燕龙办公楼一层 邮编:100096 电话:400-618-4000 传真:010-82935100 邮箱: zhanghj+itcast.cn <br>
京ICP备08001421号京公网安备110108007702
</p>
</div>
</div>
</div>
<!-- footer end -->
</body>
</html>
vue_mycart.js
window.addEventListener('load', function() {
console.log('vue_mycart')
var CartTitle = {
props: ['titles', 'allFlag'],
data: function() {
return {
msg: ''
}
},
methods: {
isSelected: function(event) {
this.$emit('change-select', event.target.checked)
}
},
// 勾选框的监听事件选用click,不用change,change时间会监听包括click触发引起的勾选变动事件以及被动勾选变动事件
template: ` <div class="cart-thead" >
<div class="t-checkbox">
<input type="checkbox" name="" id="" class="checkall" :checked="allFlag==1?true:false" @click="isSelected($event)">{{titles[0]}}
</div>
<div class="t-goods">{{titles[1]}}</div>
<div class="t-price">{{titles[2]}}</div>
<div class="t-num">{{titles[3]}}</div>
<div class="t-sum">{{titles[4]}}</div>
<div class="t-action">{{titles[5]}}</div>
</div>`
}
var CartList = {
props: ['books'],
template:
//需要在外面再包一个div,不然渲染不出来 subTotal(item.price,item.quantity)
// 勾选框的监听事件选用click,不用change,change时间会监听包括click触发引起的勾选变动事件以及被动勾选变动事件
`<div>
<div class="cart-item-list" >
<div class="cart-item check-cart-item" :key="item.id" v-for="item in books">
<div class="p-checkbox">
<input type="checkbox" name="" id="" class="j-checkbox" @click="isSelected(item.id,$event)" :checked="item.flag==1?true:false">
</div>
<div class="p-goods">
<div class="p-img">
<img :src="item.src" alt="">
</div>
<div class="p-msg">{{item.name}} </div>
</div>
<div class="p-price">¥{{item.price.toString()}}</div>
<div class="p-num">
<div class="quantity-form">
<a href="javascript:;" class="decrement" @click="minusNum(item.id,$event)">-</a>
<input type="text" class="itxt" :value="item.quantity" @blur="changeNum(item.id,$event)">
<a href="javascript:;" class="increment" @click="addNum(item.id)">+</a>
</div>
</div>
<div class="p-sum">¥{{item.subtotal}}</div>
<div class="p-action"><a href="javascript:;" @click='del(item.id)'>删除</a></div>
</div>
</div>
</div>`,
methods: {
// 定义删除功能
del: function(id) {
// 交给父组件监听
this.$emit('cart-del', id);
},
// 数量输入框中焦点失去事件发生时的数值更新
changeNum: function(id, event) {
this.$emit('num-change', {
id: id,
num: event.target.value
})
},
// 定义数量增加功能
addNum: function(id) {
this.$emit('add-num', id)
},
// 定义数量减少功能
minusNum: function(id, event) {
this.$emit('minus-num', {
id: id,
num: event.target.value
})
},
// 定义复选框改动事件
isSelected: function(id, event) {
this.$emit('change-select', { id: id, check: event.target.checked })
}
}
}
var CartTotal = {
props: ['books', 'allFlag'],
data: function() {
return {
msg: ''
}
},
computed: {
TotalAmount: function() {
var total = 0;
this.books.forEach(item => {
if (item.flag==1)
total += item.price * item.quantity
});
console.log(total);
return total.toFixed(2);
},
TotalQuantity: function() {
var totalQuantity = 0;
this.books.forEach(item => {
if (item.flag==1)
totalQuantity += item.quantity
});
return totalQuantity;
}
},
methods: {
isSelected: function(event) {
this.$emit('change-select', event.target.checked)
},
delGoods: function() {
this.$emit('del-goods')
},
delAll: function() {
this.$emit('del-all')
}
},
// 勾选框的监听事件选用click,不用change,change时间会监听包括click触发引起的勾选变动事件以及被动勾选变动事件
template: `
<div class="cart-floatbar">
<div class="select-all">
<input type="checkbox" name="" id="" class="checkall" :checked="allFlag==1?true:false" @click="isSelected($event)">全选
</div>
<div class="operation">
<a href="javascript:;" class="remove-batch" @click="delGoods"> 删除选中的商品</a>
<a href="javascript:;" class="clear-all" @click="delAll">清理购物车</a>
</div>
<div class="toolbar-right">
<div class="amount-sum">已经选<em>{{books.totalquantity}}</em>件商品</div>
<div class="price-sum">总价:<em>¥{{books.total}}</em></div>
<div class="btn-area">去结算</div>
</div>
</div>
`
}
Vue.component('my-cart', {
data: function() {
return {
// calcRes:[],
title_list: ['全选', '商品', '单价', '数量', '小计', '操作'],
all_flag: 0,
book_list:[],
}
},
mounted:function(){
this.showData()
}
,
methods: {
showData:function(){
axios.get('/goods').then(data=>{
var goods =data.data
var total=0
var totalquantity =0
goods.forEach((item,index)=>{
axios.post('/getsub',{price:item.price,quantity:item.quantity}).then(data=>{
// Vue 不允许在已经创建的实例上动态添加新的根级响应式属性,Vue无法探测普通的新增属性,此处必须使用set方法添加属性和值,否则子组件无法获取该属性值
// goods[index].subtotal = data.data.result
this.$set(goods[index],'subtotal',data.data.result)
if(item.flag==1){
total += parseFloat(data.data.result)
totalquantity += item.quantity
this.$set(goods,'total',total)
this.$set(goods,'totalquantity',totalquantity)
}
})
})
this.book_list=goods
console.log("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww")
console.log(this.book_list)
this.isAllselect()
})
},
isAllselect:function(){
console.log("所有商品都是选中状态?")
var counter = 0;
console.log("this.book_list",this.book_list)
if(this.book_list.length==0){
return this.all_flag=0
}
this.book_list.forEach((item,index)=>{
if(item.flag==1){
counter++
console.log("counter",counter)
}
console.log("counter",counter)
})
console.log("counter",counter)
if(counter==this.book_list.length){
this.all_flag=1
}else{
this.all_flag=0
}
},
delCart: function(id) {
var self = this
this.book_list.some((item,index)=>{
if(item.id==id){
axios.delete('/delete',{params:{id:id}}).then(function(data){
self.showData()
})
console.log("is it deleted?")
console.log(this.book_list)
}
})
},
numChange: function(event) {
console.log(event)
this.book_list.forEach((item, index) => {
if (item.id == event.id) {
axios.post('/changenum',{id:item.id,quantity:parseInt(event.num)}).then(data=>{
this.showData()
})
}
})
},
addNum: function(id) {
var self = this;
this.book_list.some((item, index) => {
if (item.id == id) {
self.book_list[index].quantity++;
axios.post('/changenum',{id:item.id,quantity:self.book_list[index].quantity}).then(data=>{
this.showData()
})
}
})
},
minusNum: function(event) {
var self = this;
this.book_list.some((item, index) => {
console.log(item)
if (item.id == event.id && item.quantity > 1) {
self.book_list[index].quantity--;
axios.post('/changenum',{id:item.id,quantity:self.book_list[index].quantity}).then(data=>{
this.showData()
})
}
})
},
changeSelect: function(event) {
var self = this;
console.log("单个商品选中?")
console.log(event)
this.book_list.forEach((item, index) => {
console.log(index)
// 更新图书的选中状态 并判断是否所有产品都被选中
if (item.id == event.id) {
if (event.check == true) {
// self.book_list[index].flag = 1;
// 将是否选中状态存入mysql中
axios.put('/flag',{id:event.id,flag:1}).then((data)=>{
// console.log(this.book_list)
console.log("开始渲染。。。。。。。。。。。。。。。")
this.showData()
})
} else if (event.check == false) {
// self.book_list[index].flag = 0;
axios.put('/flag',{id:event.id,flag:0}).then((data)=>{
console.log("开始渲染。。。。。。。。。。。。。。。")
this.showData()
// console.log(this.book_list)
})
}
}
})
// this.showData()
// console.log(this.book_list)
},
changeAllSelect: function(event) {
console.log("========================")
var self = this
console.log(this.book_list)
console.log(event)
if (event == true) {
this.all_flag = 1;
this.book_list.forEach((item, index) => {
self.book_list[index].flag = 1;
axios.put('/flag',{id:item.id,flag:1 }).then(data=>{
this.showData()
})
})
} else {
this.all_flag = 0;
this.book_list.forEach((item, index) => {
self.book_list[index].flag = 0;
axios.put('/flag',{id:item.id,flag:0 }).then(data=>{
this.showData()
})
})
}
// this.showData()
},
delGoods: function() {
console.log("删除选中商品功能!")
this.book_list.filter((item, index) => {
if(item.flag == 1){
axios.delete('/delete',{params:{id:item.id}}).then((data)=>{
this.showData()
})
}
})
},
delAll: function() {
console.log("清空购物车功能!")
this.book_list.forEach((item,index)=>{
axios.delete('/delete',{params:{id:item.id}}).then((data)=>{
this.showData()
})
})
},
},
template:
// 在父组件中使用 @cart-del 监听子组件事件 @get-sub="getSub($event)"
// :allFlag='all_flag' @change-select="changeAllSelect($event)
`<div><cart-title :titles='title_list' :allFlag='all_flag' @change-select="changeAllSelect($event)"></cart-title>
<cart-list :books='book_list' @change-select="changeSelect($event)" @minus-num="minusNum($event)" @add-num="addNum($event)" @cart-del="delCart($event)" @num-change="numChange($event)"></cart-list>
<cart-total :books='book_list' :allFlag='all_flag' @change-select="changeAllSelect($event)" @del-goods="delGoods($event)" @del-all="delAll($event)"><cart-total></div>`,
components: {
'cart-title': CartTitle,
'cart-list': CartList,
'cart-total': CartTotal
}
})
var v = new Vue({
el: '#app',
data: {}
})
})
goods_mysql.js
const mysql = require('mysql')
// 连接数据库
const db = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'mysql',
database: 'nodeserver',
})
// 1.创建表
// var createTable = function(){
// db.query('create table if not exists my_goods (No int unsigned primary key auto_increment, goods_url varchar(300) not null, goods_name varchar(400) not null, unit_price float(10,2) not null, quantity int unsigned not null, sub_total float(10,2) not null, status int unsigned not null)', (err, results) => {
// if (err) {
// return console.log(err.message)
// }
// console.log(results)
// })
// }
// createTable();
// 2. 写入数据this.unit_price*this.quantity
// var insertGoods = function(){
// const info = { id: 0, goods_url: "./images/p3.jpg", goods_name:'唐诗三百首+成语故事全2册 一年级课外书 精装注音儿童版 小学生二三年级课外阅读书籍',
// unit_price:12.60, quantity:1, flag:0}
// const info =[{
// id: 1,
// src: "upload/p1.jpg",
// name: "【5本26.8元】经典儿童文学彩图青少版八十天环游地球中学生语文教学大纲",
// price: 12.60,
// quantity: 1,
// flag: 0,
// isdelete:0
// },
// {
// id: 2,
// src: "upload/p2.jpg",
// name: "【2000张贴纸】贴纸书 3-6岁 贴画儿童 贴画书全套12册 贴画 贴纸儿童 汽",
// price: 24.80,
// quantity: 1,
// flag: 0,
// isdelete:0
// },
// {
// id: 3,
// src: "upload/p3.jpg",
// name: "唐诗三百首+成语故事全2册 一年级课外书 精装注音儿童版 小学生二三年级课外阅读书籍",
// price: 29.80,
// quantity: 1,
// flag: 0,
// isdelete:0
// }
// ]
// const sql = `insert into my_goods set ?`
// info.forEach((item, index)=>{
// db.query(sql, item, (err, results) => {
// if (err) {
// return console.log(err.message)
// }
// if (results.affectedRows ===1 ) {
// console.log("数据插入成功!")
// }
// })
// })
// }
// insertGoods()
// 3.查询所有数据
// var checkData = function(){
// db.query(`select * from my_goods where flag=0`, (err, results) => {
// if (err) {
// return console.log(err.message)
// }
// return results
// })
// }
// checkData()
// 4. 更新数据方法一(添加表字段)
// var updateTable = function(){
// const sql = `alter table my_books add flag int unsigned not null`
// db.query(sql, (err, results) => {
// if (err) {
// return console.log(err.message)
// }
// console.log("字段添加成功!")
// })
// }
// updateTable()
// 4. 更新数据方法二(修改flag字段的值)
// var updateStatus = function(id,flag){
// var info = { id:id, flag:flag}
// const sql = `update my_goods set flag=? where id=?`
// db.query(sql, [info.flag,info.id],(err, results) => {
// if (err) {
// return console.log(err.message)
// }
// if (results.affectedRows === 1) {
// console.log("数据修改成功!")
// }
// })
// }
// 4. 更新数据方法二(修改quantity字段的值)
// var updateQuantity = function(id,quantity){
// var info = { id:id, quantity:quantity}
// const sql = `update my_goods set quantity=? where id=?`
// db.query(sql, [info.quantity,info.id],(err, results) => {
// if (err) {
// return console.log(err.message)
// }
// if (results.affectedRows === 1) {
// console.log("数据修改成功!")
// }
// })
// }
// updateTableValue()
// 4. 更新数据方法二(修改isdelete字段的值)
// var updateIsDelete = function(id){
// var info = {id:id}
// const sql = `update my_goods set isdelete=1 where id=?`
// db.query(sql, [info.quantity,info.id],(err, results) => {
// if (err) {
// return console.log(err.message)
// }
// if (results.affectedRows === 1) {
// console.log("数据修改成功!")
// }
// })
// }
// 4. 更新数据方法二(修改isdelete字段的值,将所有的isdelete值改为0未删除状态)
var updateIsDeleteSetAll0 = function(id){
// var info = {id:id}
const sql = `update my_goods set isdelete=0`
db.query(sql, (err, results) => {
if (err) {
return console.log(err.message)
}
if (results.affectedRows === 3) {
console.log("数据修改成功!")
}
})
}
updateIsDeleteSetAll0()
// 4. 更新数据方法二(修改字段的值)
// var updateTableValue = function(){
// var info = { id:3, goods_url:"upload/p3.jpg"}
// const sql = `update my_goods set goods_url=? where id=?`
// db.query(sql, [info.goods_url,info.id],(err, results) => {
// if (err) {
// return console.log(err.message)
// }
// if (results.affectedRows === 1) {
// console.log("数据修改成功!")
// }
// })
// }
// goods = {checkAll:checkData,updateStatus:updateStatus,updateQuantity:updateQuantity}
module.exports = db
// goods.checkAll()
server.js
const express = require('express')
const cors = require('cors')
const session = require('express-session')
const db = require('./goods_mysql.js')
const bn = require('bignumber.js')
var app = express()
// 托管静态文件
app.use(express.static('shopping'))
app.use(express.json())
// 1.渲染商品接口
app.get('/goods',(req,res)=>{
console.log("visiting!")
db.query(`select * from my_goods where isdelete=0`, (err, results) => {
if (err) {
return console.log(err.message)
}
res.send(results)
console.log('数据展示成功')
return results
})
})
// 2. 删除商品接口
app.delete('/delete',(req,res)=>{
console.log("visiting!")
var info = req.query
console.log(info)
const sql = `update my_goods set isdelete=1 where id=?`
db.query(sql, info.id,(err, results) => {
if (err) {
return console.log(err.message)
}
if (results.affectedRows === 1) {
console.log("数据删除成功!")
return res.send({status:200,msg:"success"})
}
return res.send({status:404,msg:"failed"})
})
})
// 3. 变更商品数量接口
app.post('/changenum',(req,res)=>{
console.log("visiting!")
var info = req.body
console.log(info)
const sql = `update my_goods set quantity=? where id=?`
db.query(sql, [info.quantity,info.id],(err, results) => {
if (err) {
return console.log(err.message)
}
if (results.affectedRows === 1) {
console.log("商品数量修改成功!")
return res.send({status:200,msg:"success"})
}
return res.send({status:404,msg:"failed"})
})
})
// 4.变更商品选中状态接口
app.put('/flag',(req,res)=>{
console.log("visiting!")
var info = req.body
console.log(info)
// var info = { id:id, flag:flag}
const sql = `update my_goods set flag=? where id=?`
db.query(sql, [info.flag,info.id],(err, results) => {
if (err) {
return console.log(err.message)
}
if (results.affectedRows === 1) {
console.log("数据修改成功!")
return res.send({status:200,msg:"success"})
}
return res.send({status:404,msg:"failed"})
})
})
// 5. 计算单个商品合计
app.post('/getsub',(req,res)=>{
console.log('开始计算金额')
var info = req.body
var result =new bn(info.price).multipliedBy(info.quantity)
console.log(result)
res.send({result:result})
})
app.listen('80',()=>{
console.log('running on http://127.0.0.1')
})

本文通过实例解析如何结合Vue.js前端框架和Node.js后端技术,实现购物车页面的数据交互,包括HTML布局、Vue脚本及Node.js数据库连接与服务器设置等关键步骤。

482

被折叠的 条评论
为什么被折叠?



