Vue實現電商網站專案
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); }); }, } });
後記
本專案是參考 iview 作者 Aresn 書寫的《 Vue.js實戰 》一書,這本書循序漸進地對vue框架進行講解,言語簡潔、意思明瞭,適合著手Vue框架的FE,遺憾的是作者沒有給出全部原始碼,我想應該是讓讀者手動實踐,更加深入理解其原理。
在原專案上新增了登入功能
專案地址: github
筆者個人微信
筆者公眾號
技術交流群[微信]