1. 程式人生 > >說說如何使用 Vue.js 開發購物車功能

說說如何使用 Vue.js 開發購物車功能

購物車一般包含商品名稱、單價、數量等資訊,數量可以任意新增或減少,商品項也可刪除,還可以支援全選或多選:

最終效果

我們把這個小專案分為三個檔案:

  • index.html (頁面)
  • index.js (Vue 指令碼)
  • style.css (樣式)

1 index.js

首先在 js 中初始化 Vue 例項,整體模板如下:

var app = new Vue({
    el: '#app',
    data: {
     ...
    },
    mounted: function () {
       ...
    },
    computed: {
      ...
    },
    methods: {
      ...
    }

});


複製程式碼

一般來說,這裡的 data 來源於服務端資料,這裡為了簡便,所以直接定義好的資料:

data: {
        /**
         * 購物車中的商品列表
         */
        list: [
            {
                id: 1,
                name: '韓國進口海牌海苔',
                price: 39.9,
                count: 1
            },
            {
                id: 2,
                name: '印尼進口 Nabati 麗巧克(Richoco)休閒零食 巧克力味 威化餅乾'
, price: 11.8, count: 1 }, { id: 3, name: '菲律賓進口 道吉草 奶油夾', price: 6.5, count: 1 } ], //選中的商品列表,用於計算總價 checkList: [] } 複製程式碼
  • list 用於展示 購物車中的商品列表。
  • checkList 用於表示勾選中的商品列表,後面,我們會利用它來計算選中商品的總價。
mounted: function () {
        //預設全選
        this.checkAll();
        this.checkAllElement(document.querySelector(".checkAll"));
}
複製程式碼

當 mounted 時,預設全選購物車內的所有商品。

computed: {
	/**
	 * 總價
	 * @returns {string}
	 */
	totalPrice: function () {
		var total = 0;
		for (var i = 0; i < this.checkList.length; i++) {
			var item = this.checkList[i];
			total += item.price * item.count;
		}
		return total.toLocaleString();
	}
}
複製程式碼

在計算屬性中,我們定義了總價的計算方式,它會繫結勾選的 checkList 來計算總價。之所以使用 toLocaleString 方法,是因為小數部分會自動四捨五入,而且還會以千分位表示出來,很方便哦O(∩_∩)O~

methods: {
	/**
	 * 減少購買數量
	 * @param index
	 */
	reduceCount: function (index) {
		if (this.list[index].count === 1) return;
		this.list[index].count--;
	},
	/**
	 * 增加購買數量
	 * @param index
	 */
	addCount: function (index) {
		this.list[index].count++;
	},
	/**
	 * 移除商品
	 * @param index
	 */
	remove: function (index) {
		console.log("remove-index:" + index);
		this.list.splice(index, 1);

		//獲取商品序號
		var id = index + 1;
                //移除實際參與計算的商品
		var $checkList = this.checkList;
		for (var i = 0; i < $checkList.length; i++) {
			var item = $checkList[i];
			if (item.id == id) {
				$checkList.splice(i, 1);
			}
		}
	},
	/**
	 * 全選或全不選
	 * @param event
	 */
	checkAllOrNot: function (event) {
		if (event.target.checked) {//全選
			this.checkAll();
			console.log("checkList:" + this.checkList);
		} else { // 全不選
			console.log("全不選");
			this.checkInItems('noCheckAll');
			this.checkList.splice(0);//清空陣列
		}
	},
	/**
	 * 全選
	 */
	checkAll: function () {
		console.log("全選");
		this.checkInItems('checkAll');
		this.checkList = this.list.concat();//複製商品列表
	},
	/**
	 * 全選或全不選
	 * @param type checkAll:全選;其他:全不選
	 */
	checkInItems: function (type) {
		var items = document.querySelectorAll('.checkItem');
		for (var i = 0; i < items.length; i++) {
			var item = items[i];
			if (type === 'checkAll') {
				item.checked = true;
			} else {
				item.checked = false;
			}
		}
	},
	/**
	 * 勾選或不勾選
	 */
	checkItem: function (event, index) {
		console.log("checkItem");
		var element = event.target;
		var $allCheck = document.querySelector(".checkAll");
		if (element.checked) {//勾選,加入已選擇列表
			this.checkList.push(this.list[index]);
			this.checkAllElement($allCheck);
		} else {//不勾選,從已選擇列表中去除
			this.checkList.splice(index, 1);
			$allCheck.checked = false;
		}
	},
	/**
	 * 勾選全選框
	 * @param element
	 */
	checkAllElement: function (element) {
		//如果所有的商品都已被勾選,則勾選全選框
		if (this.checkList.length == this.list.length) {
			element.checked = true;
		}
	}
}
複製程式碼

在 methods 中,我們定義了以下功能方法:

  • 減少與增加購買數量。在減少購買數量方法中,我們對當前所對應商品的數量進行了二次確認,讓程式碼變得更加健壯(HTML 模板可能被修改,button 被替換為 div 或者 span,那麼 disabled 樣式就變得無效啦)。
  • 移除某件商品。因為購物車中的商品列表與實際勾選的商品列表數量上有可能存在差異,所以我們必須通過找到商品 ID 再進行刪除。
  • 勾選相關操作(全選、全不選、單選、單不選等)

2 style.css

[v-cloak] {
    display: none;
}

table {
    border: 1px solid #e9e9e9;
    border-collapse: collapse;
    border-spacing: 0;
    empty-cells: show;
}



th {
    font: bold 12px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
    color: #4f6b72;
    border-right: 1px solid #C1DAD7;
    border-bottom: 1px solid #C1DAD7;
    border-top: 1px solid #C1DAD7;
    letter-spacing: 2px;
    text-transform: uppercase;
    text-align: left;
    padding: 6px 6px 6px 12px;
    background: #CAE8EA;
}

td {
    border-right: 1px solid #C1DAD7;
    border-bottom: 1px solid #C1DAD7;
    background: #fff;
    font-size:14px;
    padding: 6px 6px 6px 12px;
    color: #4f6b72;
}
複製程式碼

這裡定義了 v-cloak 樣式,用於解決網路慢時的閃屏問題。還定義了表格的相關樣式。

3 index.html

接著在 index.html 中引入 Vue 指令碼與樣式檔案。基本模板如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>購物車</title>
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="app" v-cloak>
   ...
</div>


<script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script>
<script src="index.js"></script>
</body>
</html>
複製程式碼

因為有可能購物車中的商品被全部刪除,所以我們在此加了判斷,如果列表為空,則給出友好提示:

<template v-if="list.length">
	...
</template>
<!--當購物車為空時,則提示-->
<div v-else>購物車內暫時沒有商品</div>
複製程式碼

接著用 table 來展示購物車內的商品列表:

<table>
	<thead>
	<tr>
		<th><input id="checkAll" type="checkbox" class="checkAll" @click="checkAllOrNot($event)"></th>
		<th>序號</th>
		<th>商品</th>
		<th>單價</th>
		<th>數量</th>
		<th>操作</th>
	</tr>
	</thead>
	<tbody>
	<tr v-for="(item,index) in list">
		<td><input type="checkbox" class="checkItem" @click="checkItem($event,index)"></td>
		<td>{{index+1}}</td>
		<td>{{item.name}}</td>
		<td>{{item.price}}</td>
		<td>
			<button @click="reduceCount(index)" :disabled="item.count===1">-</button>
			{{item.count}}
			<button @click="addCount(index)">+</button>
		</td>
		<td>
			<button @click="remove(index)">刪除</button>
		</td>
	</tr>
	</tbody>
</table>
<div>總價:¥{{totalPrice}}</div>
複製程式碼
  • 使用 v-for 指令,迴圈迭代出商品列表。
  • 表格內的每一個勾選框與按鈕都綁定了相應的事件。全選框與每一行的勾選框還傳入了原生 DOM 事件 $event,用於獲取當前所操作的元素。 *這裡對減少商品數量的按鈕進行了判斷,當相應商品的數量只剩下一個時,繫結 disabled 樣式,讓它變成不可用。

4 演示

本文示例 DEMO