VUE实现商城系统

目录

产品预览

准备工作

项目开始

页面结构和根组件 app.vue

编写底部导航栏

编写路由

编写Home页面

顶部标题栏

轮播图


产品预览

VUE实现商城系统_第1张图片VUE实现商城系统_第2张图片VUE实现商城系统_第3张图片

准备工作

src目录下创建项目

  • api
  • assets(fonts, img, js, scss)
  • base
  • components
  • pages
  • router

1、引入assets下的字体文件,然后配置scss。(_variables.scss、_mixins.scss、_reset.scss、_icons.scss、_base.scss、index.scss  加入下划线是为了不被编译为css,统一在index中引入 )

//引入 main.js
import 'assets/scss/index.scss';

2、配置mian.js  引入index.scss完成基础配置。sass引入无法识别、需要引入两个插件sass-loader、node-sass

cnpm install [email protected] --save-dev
cnpm install --save-dev node-sass

3、安装一些包 babel-polyfill   fastclick、  然后在mian.js引入

安装
cnpm install --save-dev babel-polyfill 
cnpm install --save-dev fastclick

引入  main.js
import 'babel-polyfill'
import fastclick from 'fastclick'

fastclick.attach(document.body);

4、路由下的@符号是别名的意思,我们可以去build下的webpack.base.conf.js文件去修改。修改后路由下就可以用别名作为路径。

//原来别名
alias: {
  '@': resolve('src'),
  'abc': resolve('src'),
}

//修改后
alias: {
  'api': resolve('src/api'),
  'assets': resolve('src/assets'),
  'base': resolve('src/base'),
  'components': resolve('src/components'),
  'pages': resolve('src/pages')
}

项目开始

页面结构和根组件 app.vue




/*_container.scss*/
@import "mixins";
.g-container {
  overflow: hidden;
  position: relative;
  width: 100%;
  max-width: 640px;
  min-width: 320px;
  height: 100%;
  margin: 0 auto;
}

.g-view-container {
  height: 100%;
  padding-bottom: $tabbar-height;
}
.g-content-container {
  height: 100%;
  padding-top: $navbar-height;
}

.g-header-container {
  position: absolute;
  left: 0;
  top: 0;
  z-index: $navbar-z-index;
  width: 100%;
}

.g-footer-container {
  position: absolute;
  left: 0;
  bottom: 0;
  z-index: $tabbar-z-index;
  width: 100%;
  box-shadow: 0 0 10px 0 hsla(0, 6%, 58%, 0.6);
}


.g-backtop-container {
  position: absolute;
  z-index: $backtop-z-index;
  right: 10px;
  bottom: $tabbar-height + 10px;
}


如果想要保持占满全屏  不溢出需要全局设置body和html  宽高、溢出隐藏

html, body {
  overflow: hidden;
  width: 100%;
  height: 100%;
}

编写底部导航栏

//app.vue 界面引入自定义底部导航组件



//commponents下tabber  index.vue




/*_tabber.scss */
@import "mixins";

.g-tabbar {
  display: flex;
  width: 100%;
  height: $tabbar-height;
  background-color: #fff;

  &-item {
    flex: 1;
    @include flex-center(column);

    .iconfont {
      margin-bottom: 4px;
      font-size: $icon-font-size;
    }
  }
}
//_mixins
@import "variables";

// flex-center
@mixin flex-center($direction: row) {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: $direction;
}

效果

编写路由

创建页面并配置路由,home、product、category、cart、personal、seach

注意:*通配符  如果上面没有匹配到就导航到home、() => import('pages/home')路由懒加载,只在显示是加载页面信息。

//router配置
import Vue from 'vue'
import Router from 'vue-router'
// import Home from 'pages/home'
// import Category from 'pages/category'
// import Cart from 'pages/cart'
// import Personal from 'pages/personal'
// import Product from 'pages/product'
// import Search from 'pages/search'

Vue.use(Router)

const routes = [
    {
      name: 'home',
      path: '/home',
      component: () => import('pages/home'),
      children: [
        {
          name: 'home-product',
          path: 'product/:id',
          component: () => import('pages/product')
        }
      ]
    },
    {
      name: 'category',
      path: '/category',
      component: () => import('pages/category')
    },
    {
      name: 'cart',
      path: '/cart',
      component: () => import('pages/cart')
    },
    {
      name: 'personal',
      path: '/personal',
      component: () => import('pages/personal')
    },
    {
      name: 'search',
      path: '/search',
      component: () => import('pages/search')
    },
    {
      path: '*',
      redirect: '/home'
    }
]

export default new Router({
  routes
})

编写Home页面

顶部标题栏

//home下  index.vue




//home下 header.vue




//base下navbar





轮播图

安装vue-awesome-swiper

cnpm install --save-dev [email protected]

//main.js 全局引入css
import 'swiper/dist/css/swiper.css'
//home 下 index.vue




//header.vue




//base下创建 slider 下创建index.vue





//config.js
export const sliderOptions = {
    direction: 'horizontal',
    loop: true,
    interval: 0,
    pagination: true,
}

网络请求轮播图地址

安装axios插件,

cnpm install --save-dev axios 
//home 下的 index.vue





//api下的  home.js
import axios from 'axios';
import { SUCC_CODE, TIMEOUT } from './config';

// 获取幻灯片数据 -- ajax
export const getHomeSlider = () => {
    return axios.get('http://www.imooc.com/api/home/slider', {
        //这里是为了延迟10s 让网络超时  执行catch
        // timeout: TIMEOUT
    }).then(res => {
        console.log(res)
        if(res.data.code === SUCC_CODE){
            return res.data.slider
        }

        throw new Error('没有成功获取到数据!')
    }).catch(err => {
        if (err){
            console.log(err);
        }

        return [
            {
                linkUrl: 'https://www.imooc.com',
                picUrl: require('assets/img/404.png')
            }
        ]
    }).then(data => {
        // 这里是延迟1s返回  为了加  正在加载效果
        return new Promise(resolve => {
            setTimeout(() => {
                resolve(data);
            }, 1000);
        });
    })
};
//api 下的 config.js
export const SUCC_CODE = 0

export const TIMEOUT = 10000;

正在加载组件

//home 下  slider.vue  引入正在加载组件并根据轮播图是否有数据显示





//base下 slider组件  实现正在加载  




滚动条组件

//home内引入 scroll组件




//scroll组件




导航面板

在home引入  nav.vue

//nav.vue





//config.js
export const sliderOptions = {
    direction: 'horizontal',
    loop: true,
    interval: 0,
    pagination: true,
}

export const navItems = [
    // 原nav.uve的数据
    {
      linkUrl: 'https://www.imooc.com',
      picUrl: require('./img/nav-item-1.png'),
      text: '拍卖'
    },
    {
      linkUrl: 'https://www.imooc.com',
      picUrl: require('./img/nav-item-2.png'),
      text: '拍卖'
    },
    {
      linkUrl: 'https://www.imooc.com',
      picUrl: require('./img/nav-item-3.png'),
      text: '拍卖'
    },
    {
      linkUrl: 'https://www.imooc.com',
      picUrl: require('./img/nav-item-4.png'),
      text: '拍卖'
    },
    {
      linkUrl: 'https://www.imooc.com',
      picUrl: require('./img/nav-item-5.png'),
      text: '拍卖'
    },
    {
      linkUrl: 'https://www.imooc.com',
      picUrl: require('./img/nav-item-6.png'),
      text: '拍卖'
    },
    {
      linkUrl: 'https://www.imooc.com',
      picUrl: require('./img/nav-item-7.png'),
      text: '拍卖'
    },
    {
      linkUrl: 'https://www.imooc.com',
      picUrl: require('./img/nav-item-8.png'),
      text: '拍卖'
    },
    {
      linkUrl: 'https://www.imooc.com',
      picUrl: require('./img/nav-item-9.png'),
      text: '拍卖'
    },
    {
      linkUrl: 'https://www.imooc.com',
      picUrl: require('./img/nav-item-10.png'),
      text: '拍卖'
    }
  ];
  

热卖推荐组件

安装jsonp、安装vue-lazyload

cnpm install --save-dev jsonp
cnpm install vue-lazyload --save-dev

main.js引入
import VueLazyload from 'vue-lazyload';

Vue.use(VueLazyload, {
  preLoad: 1,
  error: require('assets/img/error.png'),
  loading: require('assets/img/loading.gif'),
  attempt: 1
});
//home下index.vue 注意:对组件封装  并且数据加载完成后注意刷新




//home下recommend  封装热卖商品组件 




//base下  封装scroll组件




//base下loading组件




jsonp请求

//api下封装  home.js  请求jsonp   
import axios from 'axios';
import jsonp from 'assets/js/jsonp';
import {SUCC_CODE, TIMEOUT, HOME_RECOMMEND_PAGE_SIZE, jsonpOptions} from './config';

// 获取幻灯片数据 -- ajax
export const getHomeSlider = () => {
    return axios.get('http://www.imooc.com/api/home/slider', {
        //这里是为了延迟10s 让网络超时  执行catch
        // timeout: TIMEOUT
    }).then(res => {
        // console.log(res)
        if(res.data.code === SUCC_CODE){
            return res.data.slider
        }

        throw new Error('没有成功获取到数据!')
    }).catch(err => {
        if (err){
            console.log(err);
        }

        return [
            {
                linkUrl: 'https://www.imooc.com',
                picUrl: require('assets/img/404.png')
            }
        ]
    }).then(data => {
        // 这里是延迟1s返回  为了加  正在加载效果
        return new Promise(resolve => {
            setTimeout(() => {
                resolve(data);
            }, 1000);
        });
    })
};

// 获取热门推荐数据--jsonp
export const getHomeRecommend = (page = 1, psize = HOME_RECOMMEND_PAGE_SIZE) => {
    const url = 'https://ju.taobao.com/json/tg/ajaxGetItemsV2.json';
    const params = {
      page,
      psize,
      type: 0,
      frontCatId: ''
    };
  
    return jsonp(url, params, jsonpOptions).then(res => {
        console.log('jsonp', res);
      if (res.code === '200') {
        return res;
      }
  
      throw new Error('没有成功获取到数据!');
    }).catch(err => {
      if (err) {
        console.log(err);
      }
    }).then(res => {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve(res);
        }, 1000);
      });
    });
  };
//home下 config.js
export const SUCC_CODE = 0;

export const TIMEOUT = 10000;

export const HOME_RECOMMEND_PAGE_SIZE = 20;

export const jsonpOptions = {
  param: 'callback',
  timeout: TIMEOUT
};

封装基本jsonp

//assets 下面 js  jsonp.js 封装基本jsonp
import jsonp from 'jsonp';

const parseParam = param => {
    let params = [];
  
    for (const key in param) {
      params.push([key, encodeURIComponent(param[key])]);
    }
    // [[page, 1], [pszie, 20]]
    return params.map(value => value.join('=')).join('&');
    // [[page, 1], [pszie, 20]]
    // [page=1, psize=20]
    // page=1&psize=20
  };

export default (url, data, options) => {
    url += (url.indexOf('?') < 0 ? '?' : '&') + parseParam(data)

    // jsonp(url, opti)
    return new Promise((resolve, reject) => {
        jsonp(url, options, (err, data) => {
            if(err) {
                reject(err)
            } else {
                resolve(data)
            }
        });
    })
}

下拉刷新、上拉加载

下拉提示文字变化、松手刷新、刷新幻灯片。上拉加载更多。

注意:下拉刷新轮播图后需要更新轮播图,但是loop没有改变,拉到最后一页有bug。解决方法:查找重新加载api,但是官方未提供。那么我们采用给组件变换KEY来达到重新加载,这个是VUE特性。

资源地址

 

 

 

你可能感兴趣的:(ES6,VUE)