zoukankan      html  css  js  c++  java
  • vue+vue-router+vuex实战

    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

    需求分析

    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('账号或密码错误');
    }
    

    数据过滤与排序处理

    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,欢迎加好友一起交流技术

    参考资料

    Vue.js实战
    Vue.js

  • 相关阅读:
    【mybatis】02-spring集成
    【Spring】xxAware
    【性能调优】Arthas
    【算法】其他算法(字典树Trie等)
    【多线程】JDK源码类图
    POJ-1251-Jungle Roads
    Prim算法模板
    敌兵布阵-线段树(1)
    hdu-1541-Stars (树状数组)
    母牛生小牛
  • 原文地址:https://www.cnblogs.com/ccylovehs/p/10560159.html
Copyright © 2011-2022 走看看