在学习Vue框架基础语法后,第一个实践便是常见的购物车组件,基本使用了到目前第三章学的各种基础Vue语法,体会到了Vue的强大之处 。
1 重复结构的节点可以只写一个然后自动重复生成和渲染数据 ,
2 操作数据时 变化数据 视图也会变化
3 input双向绑定 减少对数据操作
4 在事件中可以使用事件修饰符 和data中bool变量 来限制事件的执行条件 传参也能使用date中变量
5 有深度监听 可以很方便的对变化的数据进行操作
6 计算属性 很方便的计算数据然后将结果渲染到页面 数据变化 计算结果也会变化
7生命周期函数 可以在生命周期中 按照需求对数据进行处理
还有其他未列举的 相信在以后的使用中会感受到更多Vue的强大之处
下面便是我此次当当网购物车的部分代码 分多个模块
一 html代码
1 载入Vue 时加入判断 是否存在Vue框架 没有则调用备用CDN 注意使用document.write 时最后<\/script>要加转义 否则会不起作用
2主要使用v-if 显示隐藏商品列表 使用v-bind:class 绑定 active样式
3使用v-for 渲染商品列表 和 购物车表格
4@click中传参使用 渲染数据中的id属性 也可以直接传参对象 或者data中的数据 也可以配合data中某个bool变量 例如@click=“ bool&&add()”来限制事件的触发
5 标签中的属性也可以使用渲染数据 或者拼接
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="css/shopping.css" />
<script type="text/javascript">
if (typeof Vue == 'undefined') {
console.log('载入Vue备用CDN')
document.write('<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.0/vue.min.js"><\/script>')
}
</script>
</head>
<body>
<div class="main">
<!-- 商品列表 -->
<div class="booklist">
<p class="title"> <img src="images/shopping_myshopping.gif"> <a href="javascript:void(0)"> 全场免运费活动中</a>
</p>
<div class="allBook_box">
<p>根据您挑选的商品,当当为您推荐 <img :class="{active:allBookbool}" src="images/shopping_arrow_down.gif"
@click="allBookshow"></p>
<ul class="allBook" v-show="allBookbool">
<li v-for="item in allbook">
<ul>
<li><a href="javascript:void(0)">·{{item.bookname}}</a></li>
<li>¥{{item.price}}</li>
<li>¥{{item.discount}}</li>
<li><a href="javascript:void(0)" @click="add(item.id)">购买</a></li>
</ul>
</li>
</ul>
</div>
</div>
<!-- 购物车表格 -->
<div class="shopCar">
<p><b>您已选购以下商品</b></p>
<table border="0" cellspacing="0" cellpadding="0" id="shopBook">
<tr>
<th>商品名</th>
<th>单品积分</th>
<th>市场价</th>
<th>当当价</th>
<th>数量 </th>
<th>删除</th>
</tr>
<tr v-for="item in buygoods">
<td><a href="javascript:void(0)">{{item.bookname}}</a></td>
<td>{{item.discount*10}}</td>
<td>¥{{item.price}}</td>
<td>¥{{item.discount}}({{parseInt(item.discount*100/item.price)}}折)</td>
<td><button type="button" class="bnt" @click="btndown(item.id)">-</button> <input size="1"
v-model="item.num" /> <button type="button" class="bnt"
@click="btnadd(item.id)">+</button></td>
<td><button type="button" @click="del(item.id)">删除</button></td>
</tr>
</table>
<div class="content">
<div>
<p>您总共节省:<span>¥{{savemoney}}</span></p>
<p>可获商品积分:<span>{{sumprice*10}}</span></p>
</div>
<div>
<p>商品金额总计:<span><b>¥{{sumprice}}</b></span> <img src="images/shopping_balance.gif"> </p>
</div>
</div>
</div>
</div>
<script src="js/shopping.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
二 css样式
/* 布局 */
body,
p,
ul,
li {
padding: 0px;
margin: 0px;
list-style: none;
}
.main {
width: 950px;
height: 800px;
margin: auto;
}
a {
text-decoration: none;
}
.bnt {
line-height: 13px;
width: 16px;
height: 16px;
font-weight: bold;
font-size: 12px;
padding: 0px;
}
/* 商品列表 */
.booklist .title {
height: 50px;
line-height: 55px;
}
.booklist .title img {
vertical-align: -1px;
}
.booklist a:hover {
text-decoration: underline;
}
.allBook_box p {
line-height: 21px;
font-size: 14px;
background: url(../images/shopping_commend_bg.gif);
box-sizing: border-box;
border: 1px #000000 solid;
text-indent: 10px;
}
.allBook_box p img {
float: right;
margin-top: 3px;
margin-right: 8px;
}
.allBook {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
box-sizing: border-box;
padding: 10px 12px;
border: 1px #000000 solid;
border-top-width: 0px;
}
.allBook>li {
width: 50%;
box-sizing: border-box;
}
.allBook>li:nth-child(2n) {
border-left: 1px dashed #999;
}
.allBook ul {
display: flex;
justify-content: space-between;
font-size: 12px;
}
.allBook ul li {
line-height: 30px;
}
.allBook ul li:nth-child(1) {
width: 220px;
padding-left: 10px;
}
.allBook ul li:nth-child(2) {
width: 45px;
color: #3549cc;
text-decoration: line-through;
}
.allBook ul li:nth-child(3) {
width: 45px;
}
.allBook ul li:nth-child(4) {
padding-right: 10px;
}
.allBook ul li:nth-child(4) a {
color: #ED610C;
}
/* 购物车表格 */
.shopCar {
margin-top: 20px;
}
.shopCar p {
font-size: 15px;
padding-bottom: 10px;
}
#shopBook {
width: 100%;
line-height: 40px;
border: 1px #999 solid;
border-bottom-width: 0px;
}
#shopBook th {
font-weight: normal;
font-size: 14px;
}
#shopBook tr:not(:nth-child(1)):hover{
background-color: #edfada;
}
#shopBook tr:nth-child(1) {
line-height: 30px;
background-color: #d8e4c6;
}
#shopBook tr:not(:nth-child(1)) {
background-color: #fefbf2;
font-size: 12px;
}
#shopBook tr:not(:nth-child(1)) td {
border-bottom: 1px dashed #CCCCCC;
}
#shopBook td:not(:nth-child(1)) {
text-align: center;
}
#shopBook td:nth-child(1) {
text-indent: 25px;
width: 320px;
}
#shopBook input {
text-align: center;
}
#shopBook button{
cursor: pointer;
}
.active {
transform: rotate(180deg);
}
.content {
display: flex;
justify-content: flex-end;
height: 60px;
background-color: #cddbb8;
line-height: 26px;
padding: 10px 10px;
border: 1px #999 solid;
border-top-width: 0px;
}
.content>div:nth-child(1) {
width: 160px;
border-right: 1px solid black;
}
.content>div:nth-child(2) {
margin-left: 18px;
line-height: 55px;
}
.content>div:nth-child(2) img {
vertical-align: middle;
padding-left: 12px;
cursor: pointer;
}
.content span {
color: red;
font-size: 12px;
padding-left: 10px;
}
.content span b {
font-size: 14px;
}
三 javas Vue代码
1 使用data 属性渲染网页数据 和保存需要的数据 例如购物车内的商品
2使用methods 绑定点击事件
3使用computed 计算属性 渲染价格等
4使用watch 监听网页中的商品数量变化 相对的为data中的对象数据变化 必须使用深度监听
5使用生命周期函数 Created在创建Vue对象成功未载入节点数据 其他数据载入时
调用本地数据进行替换
let vm = new Vue({
el: '.main',
data: {
allbook: [{
id: 1,
bookname: 'JavaScript DOM编程艺术',
price: '39.00',
discount: '29.30'
},
{
id: 2,
bookname: '解禁(当当网独家首发)',
price: '28.00',
discount: '19.40'
},
{
id: 3,
bookname: '地王之王(金融危机下房地产行...',
price: '32.80',
discount: '25.10'
},
{
id: 4,
bookname: '逃庄',
price: '36.00',
discount: '27.70'
},
{
id: 5,
bookname: '深入浅出MySQL数据库开发、优...',
price: '59.00',
discount: '47.20'
},
{
id: 6,
bookname: '大玩家(马未都、王刚推荐!央...',
price: '34.80',
discount: '30.50'
},
{
id: 7,
bookname: '都市风水师--官场风水小说:一...',
price: '39.80',
discount: '20.60'
},
{
id: 8,
bookname: '国戏(以麻将术语解读宦海沉浮...',
price: '25.00',
discount: '17.30'
},
],
allBookbool: true,
buygoods: [{
id: 1,
bookname: 'JavaScript DOM编程艺术',
price: '39.00',
discount: '29.30',
num: 1
}] //已购买数组
},
methods: {
allBookshow() { //图书列表显示隐藏
this.allBookbool = !this.allBookbool
},
add(id) { //新图书添加
let repbool = false
let allbook = this.allbook
let buygoods = this.buygoods
for (let i = 0; i < buygoods.length; i++) { //判断id是否存在已购买数组中
if (buygoods[i].id == id) {
buygoods[i].num++
repbool = true
}
}
if (!repbool) { //不重复则执行
let index = ''; //重复商品在数组中下标
for (let i = 0; i < allbook.length; i++) {
if (allbook[i].id == id) {
let arr = {
...allbook[i]
} //创建新数组 加默认数量属性 放入已购买数组中
arr.num = 1
buygoods.push(arr)
// console.log(arr)
}
}
}
},
btnadd(id) { //按键添加数量 通过传参id 调用add(id)新图书添加事件
// alert(id)
this.add(id)
},
btndown(id) { //按键减少数量
// alert(id)
let buygoods = this.buygoods
for (let i = 0; i < buygoods.length; i++) {
if (buygoods[i].id == id) { //判断id与数组中一致 num属性减一
if (buygoods[i].num > 1) {
buygoods[i].num--
} else {
console.log('数量至少为1');
}
}
}
},
del(id) { //在已购买的数组中根据id删除数据
if (confirm('确定删除该行商品?')) {
// console.log(id);
let buygoods = this.buygoods
for (var i = 0; i < buygoods.length; i++) {
if (buygoods[i].id == id) {
buygoods.splice(i, 1)
}
}
}
}
},
computed: {
sumprice() { //总价 积分为总价*10
let sum = 0
for (let s of this.buygoods) {
sum += s.discount * s.num
}
return sum.toFixed(2)
},
savemoney() { //节省
let sum = 0
for (let s of this.buygoods) {
sum += (s.price - s.discount) * s.num
}
return sum.toFixed(2)
},
},
watch: {
buygoods: {
handler(newval, oldval) { //深度监听 输入num 非>=1 的数字或其他字符时 或者小数 会被赋值为1
for (let s of newval) {
if (!(s.num >= 1 && s.num % 1 == 0)) {
s.num = 1
}
};
let str = JSON.stringify(this.buygoods) //数据变化 本地重新存储
sessionStorage.buygoods = str
},
deep: true
}
},
created() {
if (sessionStorage.buygoods) { //存在本地数据则载入
let buygoods = JSON.parse(sessionStorage.buygoods)
this.buygoods = buygoods
console.log('本地有数据');
} else {
console.log('本地没有数据');
}
}
})
效果图:
在此次事件中遇到的问题
1 多层数据结构如何在网页中渲染?
2 深度监听的使用方法是什么?
3事件中 需要传参的数据选择 ?
4使用Vue时在网页渲染时 如何拼接 属性 变量 实际参数 等?
通过查阅资料 已经解决部分 问题 其他还在学习中
四 总结
经过此次使用Vue编写 当当网购物车 的实践 ,增强了对Vue的了解 和使用规范 以及使用方法 也体会到了渐进式开发 或 MVVM框架 开发的乐趣 与操作Dom来开发 的确是另一个完全不同的编写模式 希望在后面的学习中再接再厉 在脑中建立好Vue的整体使用思维。