shopping
vue
+ vue-router
+ vuex
實現電商網站
效果展示
install
- 下載程式碼:
git clone https://github.com/chenchangyuan/shopping.git
- 安裝依賴:
npm install
- 啟動專案:
npm run dev
執行環境: node v9.11.1 npm 5.6.0
需求分析
- 登入頁面、商品列表頁(網站首頁)、購物車頁(實現結算)、商品詳情頁
- 可按顏色、品牌對商品進行篩選,單擊選中,再次點選取消
- 根據價格進行升序降序、銷量降序排列
- 商品列表顯示圖片、名稱、銷量、顏色、單價
- 實時顯示購物車數量(商品類別數)
- 購物車頁面實現商品總價、總數進行結算,優惠券打折
資料儲存 & 資料處理
product.js
存放商品資料(生產環境需通過介面呼叫獲取資料)
{
id: 1,
name: 'AirPods',
brand: 'Apple',
image: '/src/images/airPods.jpg',
imageDetail: '/src/images/airPods_detail.jpg',
sales: 10000,
cost: 1288,
color: '白色'
},
複製程式碼
window.localStorage
實現資料儲存與驗證
let username = window.localStorage.getItem('username');
let password = window.localStorage.getItem('password');
if(!util.trim(this.username) || !util.trim(this.username) ){
window.alert('賬號或密碼不能為空');
return;
}
if(username === this.username && password === this.password){
this.login = false;
window.localStorage.setItem('loginStatus', 'login');
this.$store.commit('getUser', this.username);
window.alert('登陸成功,確定進入網站首頁');
window.location.href = '/list';
}else{
window.alert('賬號或密碼錯誤');
}
複製程式碼
資料過濾與排序處理
filteredAndOrderedList(){
//拷貝原陣列
let list = [...this.list];
//品牌過濾
if(this.filterBrand !== ''){
list = list.filter(item => item.brand === this.filterBrand);
}
//顏色過濾
if(this.filterColor !== ''){
list = list.filter(item => item.color === this.filterColor);
}
//排序
if(this.order !== ''){
if(this.order === 'sales'){
list = list.sort((a, b) => b.sales - a.sales);
}else if(this.order === 'cost-desc'){
list = list.sort((a, b) => b.cost - a.cost);
}else if(this.order === 'cost-asc'){
list = list.sort((a, b) => a.cost - b.cost);
}
}
return list;
}
複製程式碼
實時顯示應付總額與商品數
//購物車商品總數
countAll(){
let count = 0;
this.cartList.forEach(item => {
count += item.count;
});
return count;
},
//購物車商品總價
costAll(){
let cost = 0;
this.cartList.forEach(item => {
cost += this.productDictList[item.id].cost * item.count;
});
return cost;
}
複製程式碼
購物車結算處理
//通知Vuex,完成下單
handleOrder(){
this.$store.dispatch('buy').then(() => {
window.alert('購買成功');
})
},
複製程式碼
vue-router & vuex
vue-router路由管理/src/views/
目錄下的vue
元件進行設定,router-views
掛載所有路由,登入介面與商品列表頁面之間header做隱藏顯示處理,登入狀態下重新整理頁面跳轉至列表頁,其他頁面設定預設跳轉
跳轉處理
const router = new VueRouter(RouterConfig);
//跳轉前設定title
router.beforeEach((to, from, next) => {
window.document.title = to.meta.title;
next();
});
//跳轉後設定scroll為原點
router.afterEach((to, from, next) => {
window.scrollTo(0, 0);
});
複製程式碼
routers配置
//商品列表路由配置
const routers = [
{
path: '/list',
meta: {
title: '商品列表'
},
component: (resolve) => require(['./views/list.vue'], resolve)
},
{
path: '/product/:id',
meta: {
title: '商品詳情'
},
component: (resolve) => require(['./views/product.vue'], resolve)
},
{
path: '/cart',
meta: {
title: '購物車'
},
component: (resolve) => require(['./views/cart.vue'], resolve)
},
{
path: '/login/:loginStatus',
meta: {
title: '登入註冊'
},
component: (resolve) => require(['./views/login.vue'], resolve)
},
{
path: '*',
redirect: '/login/login'
}
];
export default routers;
複製程式碼
vuex狀態管理,各元件共享資料在state
中設定,mutation
實現資料同步,action
非同步載入
//配置Vuex狀態管理
const store = new Vuex.Store({
state: {
//商品列表資訊
productList: [],
//購物車資料,陣列形式,資料元素為物件(商品id,購買數量count)
cartList: [],
//當前使用者賬號
username: window.localStorage.getItem('username'),
//登入狀態
loginStatus: !!window.localStorage.getItem('loginStatus'),
},
getters: {
//品牌、顏色篩選
brands: state => {
const brands = state.productList.map(item => item.brand);
return util.getFilterArray(brands);
},
colors: state => {
const colors = state.productList.map(item => item.color);
return util.getFilterArray(colors);
}
},
//mutations只能以同步方式
mutations: {
//新增商品列表
setProductList(state, data){
state.productList = data;
},
//新增購物車
addCart(state, id){
const isAdded = state.cartList.find(item => item.id === id);
//如果不存在設定購物車為1,存在count++
if(isAdded){
isAdded.count++;
}else{
state.cartList.push({
id: id,
count: 1
})
}
},
//修改購物車商品數量
editCartCount(state, payload){
const product = state.cartList.find(item => item.id === payload.id);
product.count += payload.count;
},
//刪除購物車商品
deleteCart(state, id){
const index = state.cartList.findIndex(item => item.id === id);
state.cartList.splice(index, 1)
},
//清空購物車
emptyCart(state){
state.cartList = [];
},
getUser(state, username){
console.log('username',username)
state.username = username;
},
getLoginStatus(state, flag){
state.loginStatus = flag;
}
},
actions: {
//非同步請求商品列表,暫且使用setTimeout
getProductList(context){
setTimeout(() => {
context.commit('setProductList', product_data)
}, 500);
},
//購買
buy(context){
//生產環境使用ajax請求服務端響應後再清空購物車
return new Promise(resolve => {
setTimeout(() => {
context.commit('emptyCart');
resolve();
}, 500);
});
},
}
});
複製程式碼
後記
專案地址: 閱讀完本文如果對vue的理解有所幫助,請給顆star,謝謝~
筆者個人微信 gm4118679254
歡迎加好友一起交流技術