购物车案例功能:
- 创建一个Vue实例
- v-for渲染产品数据
- Filter对金额和图片进行格式化
- v-on实现产品金额的动态计算
功能比较简单,但是涉及到平时项目中常见的业务逻辑。可谓麻雀虽小,五脏俱全。
数据渲染
- vue-resource插件来获取后端数据(推荐使用vue-axios,官网说vue-resource已不再维护),这里用的是本地的json数据来模拟。引入vue.js ,vue-resource.js, 自己的js.
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="js/lib/vue-resource.js"></script>
<script src="js/cart1.js"></script>
cart.js中创建vue实例,data中声明个productList:[]来渲染数据,methods中声明函数cartView()来获取数据,mounted函数来执行这个cartView(mounted函数是el中的模板html,dom渲染完成再执行)
new Vue({
el: '#app',
data: {
productList: []
},
mounted () {
this.$nextTick(function () {
this.cartView()
})
},
methods:{
cartView() {
this.$http.get('../data/cartData.json').then(res => {
this.productList = res.data.result.list;
})
}
}
})
注意我使用都是es6的写法,这里使用箭头函数,就不需要再获取父级作用域的this了。省略了var_ this = this
官网说,mounted函数应该这样使用保险一些:
mounted: function () {
this.$nextTick(function () {
// 代码保证 this.$el 在 document 中
})
}
直接打开html是一定会出问题的,因为这里使用ajax来模拟获取后台数据产生了跨域,我使用了live-server插件来热启动,在本地的服务器上查看。
过滤器
使用过滤器来美化一下价格的样式,加上¥,并保留小数点2位。
filters: {
money(value, type) {
return '¥' + value.toFixed(2) + type
}
},
<div class="item-price">{{item.productPrice | money('元')}}</div>
全局注册过滤器可以在其它页面引用,局部过滤器只能在这个实例中使用
Vue.filter('money', function (value, type) {
return '$' + value.toFixed(2) + type
})
业务逻辑
- 商品数量的加减功能
changeNumber(item, way) {
if( way < 0) {
item.productQuantity --;
if(item.productQuantity < 1) {
item.productQuantity = 1
}
}else{
item.productQuantity ++;
}
},
<a @click="changeNumber(item,-1)">-</a>
<input type="text" value="0" disabled v-model="item.productQuantity">
<a @click="changeNumber(item, 1)">+</a>
changeNumber接受2个参数,第一个表示商品,第二个表示加或减
- 单选按钮的确认和取消
因为给的json数据里没有商品的选中和取消属性,我们就通过Vue.set来给商品注册这个属性,绑定class,如果为true,check样式就显示。并通过绑定点击事件来取反,来达到选择和取消。
selectProduct(item) {
if (typeof item.checked == 'undefined') {
this.$set(item, 'checked', true)
}else{
item.checked = !item.checked
}
}
<a class="item-check-btn" :class="{'check': item.checked}" @click="selectProduct(item)">
- 全选按钮的确认和取消
这个功能我们就可以在data中注册个属性来表示。声明属性checkAll:false ,并绑定到class上,表示默认的是没有选中。绑定点击事件,传入参数true表示全选,此时checkAllFlag中this.checkAll = true,全选生效。同理,传入false,this.checkAll = false,取消全选
<span class="item-check-btn" :class="{'check':checkAll}" @click="checkAllFlag(true)">
<a class="item-del-btn" :class="{'check':checkAll}" @click="checkAllFlag(false)" >
checkAllFlag(flag) {
this.checkAll = flag;
}
那么,怎么通过全选达到商品也被选中的效果呢?
checkAllFlag(flag) {
this.checkAll = flag;
this.productList.forEach((item, index) => {
if(typeof item.checked == 'undefined') {
this.$set(item, 'checked', flag)
}else{
item.checked = flag
}
})
}
全选的时候,传入参数true,checkAll属性为true,同时,遍历商品的列表,给商品注册checked:true。取消全选同理。
- 总金额的计算
定义一个方法来计算总计额返回给data里的totalMoney.注意的是商品被选中的时,即item.checked为true时,totalMoney才计算。
calcTotalMoney() {
this.totalMoney = 0;
this.productList.forEach((item, index) => {
if(item.checked) {
this.totalMoney += item.productPrice*item.productQuantity
}
})
}
- 删除订单功能
data中声明delFlag默认为false,小垃圾桶图标绑定事件,删除界面v-bind:class=“{‘md-show’: delFlag}” ,md-show样式在delFlag=true的时候应用了。关闭按钮绑定点击事件delFlag=false,这里注意的是有一个遮罩层,用v-if=“delFlag”来控制显示和隐藏。
小垃圾桶绑定事件delConfirm(item),让curProduct变量来保存此时的商品item。
delConfirm(item) {
this.delFlag = true;
this.curProduct = item //声明curProduct属性来保存此时的item
},
然后在删除功能中,获取这个商品item的index,再用splice方法删除。
delProduct() {
var index = this.productList.indexOf(this.curProduct)
this.productList.splice(index, 1);
this.delFlag = false
}
好了,到这里,购物车的一些基本功能基本上都实现了。
地址选配功能
跟购物车功能类似,或许数据,挂在到mounted函数上,这里不同的是用计算属性computed获取数组的3项,然后在dom中渲染,
computed: {
filterAddress: function () {
return this.addressList.slice(0, this.limitNum) //获取addressList的前三个
}
},
<li v-for="(item,index) in filterAddress" ></li>
列表选项问题,配送方式的点击选中如下实现:
<li :class="{'check':shippingMethod == 1}" @click="shippingMethod = 1">
<div class="name">标准配送</div>
<div class="price">Free</div>
</li>
<li :class="{'check':shippingMethod == 2}" @click="shippingMethod = 2">
<div class="name">高级配送</div>
<div class="price">180</div>
</li>
地址列表如下实现:
<li v-for="(item,index) in filterAddress" :class="{'check': index == currentIndex}" @click="currentIndex = index">
点击此地址,将索引index赋值给currentIndex,那么cunrrentIndex==index成立时,check样式实现。
这里是很好的2种不同情况下的实现方式,在以后的项目中可能会经常遇到。