vue+vue-router+vuex實戰

shopping

vue + vue-router + vuex實現電商網站javascript

效果展現

install

  • 下載代碼: git clone https://github.com/chenchangyuan/shopping.git
  • 安裝依賴: npm install
  • 啓動項目: npm run devhtml

    運行環境: node v9.11.1 npm 5.6.0vue

需求分析

  1. 登陸頁面、商品列表頁(網站首頁)、購物車頁(實現結算)、商品詳情頁
  2. 可按顏色、品牌對商品進行篩選,單擊選中,再次點擊取消
  3. 根據價格進行升序降序、銷量降序排列
  4. 商品列表顯示圖片、名稱、銷量、顏色、單價
  5. 實時顯示購物車數量(商品類別數)
  6. 購物車頁面實現商品總價、總數進行結算,優惠券打折

數據存儲 & 數據處理

  • 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('帳號或密碼錯誤');
}

數據過濾與排序處理java

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;
}

實時顯示應付總額與商品數node

//購物車商品總數
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;
}

購物車結算處理git

//通知Vuex,完成下單
handleOrder(){
    this.$store.dispatch('buy').then(() => {
        window.alert('購買成功');
    })
},

vue-router & vuex

vue-router路由管理/src/views/目錄下的vue組件進行設置,router-views掛載全部路由,登陸界面與商品列表頁面之間header作隱藏顯示處理,登陸狀態下刷新頁面跳轉至列表頁,其餘頁面設置默認跳轉github

跳轉處理ajax

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配置vue-router

//商品列表路由配置
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

//配置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,歡迎加好友一塊兒交流技術

參考資料

Vue.js實戰
Vue.js

相關文章
相關標籤/搜索