利用vue.js写一个购物车结算
笔者自学前端两个月了,之前什么轮播图,自动加载的功能,写了就忘了,还是太菜了。于是想开个博客来记录一下自己学习的历程。第一篇,献给这个购物车。大概下面那个效果把。
- 先搭建一个html结构。
第一个导入的js库即vue大家自己去下载哈
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="css.css">
<script type="text/javascript" src="vue.js"></script>
<title>购物车,结算你的商品!</title>
</head>
<body>
<div id="el">
<input type="text" placeholder="请输入商品名" class="text" v-model="commodity">
<input type="text" placeholder="请输入单价" class="text" v-model="price">
<a class="submit" @click="add()">添加商品</a>
<div id="table"><span class="span">商品名</span>
<span class="span">单价(元/瓶)</span>
<span class="span">数量</span>
<span class="span">合计(元)</span>
</div>
<script type="text/javascript" src="js.js"></script>
</div>
</body>
</html>
css样式就不写了,然后我们就考虑到我们有一个增加商品的功能,一次增加四个值,这个可以用vue组件解决(注意js里return后面的第一个括号必须和return在一行,不然会返回undefined)
vue 可以实现数据的绑定,比起js的dom操作简单不少,我们通过vue来简便购物车的代码。
需要了解的语法:v-on即@ 触发事件
v-bind 即: 绑定属性
v-model 绑定表单双向绑定
{{}}双括号 里面放的值是data里的属性名
还有v-for和组件相关语法,组件自己也不太懂呀,作为vue的最强大功能,传值复杂的不行,想到以后还要看vue源码,太苦了呀(哭)
<todo-item
v-for="item in groceryList"
v-bind:todo="item"
v-bind:key="item.id">
</todo-item>//两个代码块放一起了,上面是HTML下面是js,grocerylist是我们
//通过add函数往里面传值的列表,add函数下文会给出
component('todo-item', {
// todo-item 组件现在接受一个
// "prop",类似于一个自定义特性。
// 这个 prop 名为 todo。
props: ['todo'],
data:function () {
return{
count:1},
template: '<div ><span class="span">{{todo.text1}}</span>'+
'<span class="span">{{todo.text2}}</span><a class="submit1" @click="if(count>1)count--;" >-</a>'+
'<span class="span3">{{count}}</span><a class="submit1" @click="count++" >+</a>'+
'<span class="span4">{{todo.text2*count}}</span>'+
'</div>'
- 然后呢基本的搭建就形成了,我们还要统计总价这个工作要做,要知道总价的数据存在vue实例的data里面,我们要从组件发送组件的数据传给总价分布代码如下
add: function () {
this.groceryList.push({
id: this.adid++,
text1: this.commodity,
text2: this.price
});
this.commodity = '';
this.total = this.total + this.price * 1;
this.price = '';
},
gets: function (msg) {
this.total = this.total + msg * 1
}
,
gets1: function (msg) {
this.total = this.total - msg * 1
}
//上面是vue实例里的方法,下面是组件里的方法
methods:{
set:function(){
this.$emit("hey",this.todo.text2);},
set1:function(){
if (this.count>1)this.$emit("hey1",this.todo.text2);}
//再下面是html
<todo-item
@hey="gets"
@hey1="gets1"
v-for="item in groceryList"
v-bind:todo="item"
v-bind:key="item.id">
</todo-item>
//特别需要注意!!!我们的外部属性挂载一定要挂载组件标签上!!!笔者
//在这里卡了好久,放在跟元素el的div里面,就是传不了值。(即@hey要在
//todo-item标签里面),还有一点要注意的,传值时要注意值是否正确,我之
//前传this.text2疯狂调试不知错在哪,结果发现要传this.todo.text2
}
第一篇博文,都不知道怎么讲自己的心路历程,从0开始vue,写了个购物车,其实还有很多优化都没做好,比如有效输入的判断呀,别被html注入给搞崩了 。以后的前端后端项目,还有算法竞赛的好题,都写博客吧,可以锻炼自己的语言表达能力,反思自己思路错在哪。最后附上项目的所有代码。
//html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="css.css">
<script type="text/javascript" src="vue.js"></script>
<title>购物车,结算你的商品!</title>
</head>
<body>
<div id="el">
<input type="text" placeholder="请输入商品名" class="text" v-model="commodity">
<input type="text" placeholder="请输入单价" class="text" v-model="price">
<a class="submit" @click="add()">添加商品</a>
<div id="table"><span class="span">商品名</span>
<span class="span">单价(元/瓶)</span>
<span class="span">数量</span>
<span class="span">合计(元)</span>
</div>
<todo-item
@hey="gets"
@hey1="gets1"
v-for="item in groceryList"
v-bind:todo="item"
v-bind:key="item.id">
</todo-item>
<div class="span span5" >总计{{total}}</div>
<script type="text/javascript" src="js.js"></script>
</div>
</body>
</html>
//css文件
*{margin: 0;
padding: 0;}
.text{width:15%;
height: 30px;
margin-left: 5%;
border: solid gray 2px;
border-radius: 10%;}
.submit{
height: 25px;
width: 7%;
margin-left: 5%;
border: solid gray 2px;
border-radius: 10%;
background-color: rgba(30,144,255,0.7);
color: white;
display: inline-block;
cursor: pointer;
text-align: center;
}
.submit1{height: 20px;
width: 20px;
border: solid gray 2px;
border-radius: 50%;
background-color: rgba(30,144,255,0.7);
color: white;
display: inline-block;
cursor: pointer;
text-align: center;}
#table{hight:40px;
width: 100%;
background-color: pink;}
.span{display: inline-block;
height: 70px;
width: 20%;
margin-left: 40px;
font-size: 30px;
line-height: 70px;}
.span3{display: inline-block;
height: 70px;
width: 5%;
font-size: 30px;
line-height: 70px;
margin-left: 40px;}
.span4{display: inline-block;
height: 70px;
width: 5%;
font-size: 30px;
line-height: 70px;
margin-left: 20%;}
.span5{float: right;}
//js vue库自行下载
var vm=new Vue({
el:'#el',
data:{
commodity:'',
price:'',
groceryList: [
],
adid:0,
total:0
},
methods: {
add: function () {
this.groceryList.push({
id: this.adid++,
text1: this.commodity,
text2: this.price
});
this.commodity = '';
this.total = this.total + this.price * 1;
this.price = '';
},
gets: function (msg) {
this.total = this.total + msg * 1
}
,
gets1: function (msg) {
this.total = this.total - msg * 1
}
}
})
Vue.component('todo-item', {
// todo-item 组件现在接受一个
// "prop",类似于一个自定义特性。
// 这个 prop 名为 todo。
props: ['todo'],
data:function () {
return{
count:1,
}
},
template: '<div ><span class="span">{{todo.text1}}</span>'+
'<span class="span">{{todo.text2}}</span><a class="submit1" @click="set1()" @click="if(count>1)count--;" >-</a>'+
'<span class="span3" >{{count}}</span><a class="submit1" @click="set()" @click="count++" >+</a>'+
'<span class="span4" >{{todo.text2*count}}</span>'+
'</div>',
methods:{
set:function(){
this.$emit("hey",this.todo.text2);},
set1:function(){
if (this.count>1)this.$emit("hey1",this.todo.text2);}
}
})