├── public ├── favicon.ico └── index.html ├── babel.config.js ├── src ├── assets │ ├── img │ │ ├── common │ │ │ ├── top.png │ │ │ ├── placeholder.png │ │ │ ├── back.svg │ │ │ └── collect.svg │ │ ├── detail │ │ │ ├── cart.png │ │ │ └── detail_bottom.png │ │ ├── home │ │ │ └── recommend_bg.jpg │ │ ├── cart │ │ │ └── tick.svg │ │ └── tabbar │ │ │ ├── profile.svg │ │ │ ├── home.svg │ │ │ ├── home_active.svg │ │ │ ├── profile_active.svg │ │ │ ├── cart.svg │ │ │ ├── cart_active.svg │ │ │ ├── category.svg │ │ │ └── category_active.svg │ └── css │ │ ├── base.css │ │ └── normalize.css ├── store │ ├── constant.js │ ├── getters.js │ ├── mutations.js │ ├── index.js │ └── actions.js ├── components │ ├── common │ │ ├── swiper │ │ │ ├── index.js │ │ │ ├── SwiperItem.vue │ │ │ └── Swiper.vue │ │ ├── backTop │ │ │ └── BackTop.vue │ │ ├── toast │ │ │ ├── index.js │ │ │ └── Toast.vue │ │ ├── tabbar │ │ │ ├── TabBar.vue │ │ │ └── TabBarItem.vue │ │ ├── navbar │ │ │ └── NavBar.vue │ │ └── scroll │ │ │ └── Scroll.vue │ └── content │ │ ├── checkGoodsBtn │ │ └── CheckGoodsBtn.vue │ │ ├── tabControl │ │ └── TabControl.vue │ │ ├── goods │ │ ├── GoodsList.vue │ │ └── GoodsListItem.vue │ │ └── mainTabBar │ │ └── MainTabBar.vue ├── common │ ├── utils.js │ └── mixin.js ├── network │ ├── category.js │ ├── home.js │ ├── request.js │ └── detail.js ├── views │ ├── home │ │ ├── childComps │ │ │ ├── FeatureView.vue │ │ │ ├── RecommendView.vue │ │ │ └── HomeSwiper.vue │ │ └── Home.vue │ ├── profile │ │ └── Profile.vue │ ├── detail │ │ ├── childComps │ │ │ ├── DetailRecommend.vue │ │ │ ├── DetailSwiper.vue │ │ │ ├── DetailNavBar.vue │ │ │ ├── DetailGoodsInfo.vue │ │ │ ├── DetailGoodsParams.vue │ │ │ ├── DetailBottomBar.vue │ │ │ ├── DetailBaseInfo.vue │ │ │ ├── DetailCommentInfo.vue │ │ │ └── DetailShopInfo.vue │ │ └── Detail.vue │ ├── category │ │ ├── childComps │ │ │ ├── CategorySideContentItem.vue │ │ │ ├── CategorySideContent.vue │ │ │ └── CategorySideBar.vue │ │ └── Category.vue │ └── cart │ │ ├── childComps │ │ ├── CartList.vue │ │ ├── CartListItem.vue │ │ └── CartBottomBar.vue │ │ └── Cart.vue ├── App.vue ├── main.js └── router │ └── index.js ├── .editorconfig ├── .gitignore ├── vue.config.js ├── package.json └── README.md /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sodaxiang/supermall/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/assets/img/common/top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sodaxiang/supermall/HEAD/src/assets/img/common/top.png -------------------------------------------------------------------------------- /src/assets/img/detail/cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sodaxiang/supermall/HEAD/src/assets/img/detail/cart.png -------------------------------------------------------------------------------- /src/store/constant.js: -------------------------------------------------------------------------------- 1 | export const ADD_TO_CART = 'add_to_cart'; 2 | export const ADD_TO_COUNTER = 'add_to_counter'; -------------------------------------------------------------------------------- /src/assets/img/home/recommend_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sodaxiang/supermall/HEAD/src/assets/img/home/recommend_bg.jpg -------------------------------------------------------------------------------- /src/assets/img/common/placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sodaxiang/supermall/HEAD/src/assets/img/common/placeholder.png -------------------------------------------------------------------------------- /src/assets/img/detail/detail_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sodaxiang/supermall/HEAD/src/assets/img/detail/detail_bottom.png -------------------------------------------------------------------------------- /src/components/common/swiper/index.js: -------------------------------------------------------------------------------- 1 | import Swiper from './Swiper'; 2 | import SwiperItem from './SwiperItem'; 3 | 4 | export { 5 | Swiper, SwiperItem 6 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailling_whitespace = true -------------------------------------------------------------------------------- /src/store/getters.js: -------------------------------------------------------------------------------- 1 | export default { 2 | cartList(state){ 3 | return state.cartList; 4 | }, 5 | cartListLength(state){ 6 | return state.cartList.length; 7 | } 8 | } -------------------------------------------------------------------------------- /src/common/utils.js: -------------------------------------------------------------------------------- 1 | export function debounce(func, delay=0){ 2 | let timer = null; 3 | return function(){ 4 | if(timer) clearTimeout(timer); 5 | timer = setTimeout(()=>{ 6 | func.apply(this); 7 | }, delay); 8 | } 9 | } -------------------------------------------------------------------------------- /src/store/mutations.js: -------------------------------------------------------------------------------- 1 | import { 2 | ADD_TO_CART, 3 | ADD_TO_COUNTER 4 | } from './constant'; 5 | 6 | export default { 7 | [ADD_TO_CART](state,payload){ 8 | state.cartList.push(payload); 9 | }, 10 | [ADD_TO_COUNTER](state, payload){ 11 | payload.num ++ ; 12 | } 13 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports ={ 2 | configureWebpack: { 3 | resolve: { 4 | alias: { 5 | // 'assets': 'src/assets', 6 | // 'common': 'src/common', 7 | // 'components': 'src/components', 8 | // 'views': 'src/views', 9 | } 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/network/category.js: -------------------------------------------------------------------------------- 1 | import { request } from './request'; 2 | 3 | export function getAllCategory(){ 4 | return request({ 5 | url: '/category' 6 | }) 7 | } 8 | export function getSubCategory(maitKey) { 9 | return request({ 10 | url: '/subcategory', 11 | params:{ 12 | maitKey 13 | } 14 | }) 15 | } -------------------------------------------------------------------------------- /src/components/common/swiper/SwiperItem.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 22 | -------------------------------------------------------------------------------- /src/network/home.js: -------------------------------------------------------------------------------- 1 | import { request } from './request'; 2 | 3 | export function getHomeMultidata() { 4 | return request({ 5 | url: '/home/multidata' 6 | }); 7 | } 8 | 9 | export function getHomeGoods(type, page){ 10 | return request({ 11 | url: '/home/data', 12 | params: { 13 | type, 14 | page 15 | } 16 | }) 17 | } -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | 4 | import mutations from './mutations'; 5 | import actions from './actions'; 6 | import getters from './getters'; 7 | 8 | Vue.use(Vuex); 9 | 10 | const state = { 11 | cartList:[] 12 | }; 13 | 14 | export default new Vuex.Store({ 15 | state, 16 | mutations, 17 | actions, 18 | getters 19 | }) -------------------------------------------------------------------------------- /src/assets/img/cart/tick.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/common/backTop/BackTop.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 23 | 24 | -------------------------------------------------------------------------------- /src/views/home/childComps/FeatureView.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/components/common/toast/index.js: -------------------------------------------------------------------------------- 1 | import Toast from './Toast'; 2 | 3 | const obj = {}; 4 | 5 | obj.install = function(Vue){ 6 | // 1. 创建组件构造器 7 | const toastConstructor = Vue.extend(Toast); 8 | 9 | // 2.new的方式,根据组件构造器,创建一个组件对象 10 | const toast = new toastConstructor(); 11 | 12 | // 3.将组件对象手动挂载到某一个DOM元素上 13 | toast.$mount(document.createElement('div')); 14 | 15 | // 4.toast.$el对应的就是div 16 | document.body.appendChild(toast.$el); 17 | 18 | Vue.prototype.$toast = toast; 19 | } 20 | export default obj; -------------------------------------------------------------------------------- /src/views/profile/Profile.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | 20 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/components/common/tabbar/TabBar.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 | 31 | 32 | -------------------------------------------------------------------------------- /src/assets/img/common/back.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 24 | 25 | 28 | -------------------------------------------------------------------------------- /src/components/common/navbar/NavBar.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 29 | 30 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | import VueLazyload from 'vue-lazyload'; 4 | 5 | import router from './router'; 6 | import store from './store'; 7 | 8 | import toast from './components/common/toast'; 9 | 10 | Vue.config.productionTip = false 11 | 12 | // 注册事件总总线 13 | Vue.prototype.$bus = new Vue(); 14 | // 安装toast插件 15 | Vue.use(toast); 16 | 17 | // 使用vue-lazyload 18 | Vue.use(VueLazyload, { 19 | // error: './assets/common/placeholder.png', 20 | loading: require('./assets/img/common/placeholder.png') 21 | }); 22 | new Vue({ 23 | render: h => h(App), 24 | router, 25 | store 26 | }).$mount('#app') 27 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/network/request.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export function request(config) { 4 | 5 | //1. 创建axios实例 6 | const instance = axios.create({ 7 | baseURL: '找老师要', 8 | timeout: 5000, 9 | }); 10 | 11 | //2. axios拦截器 12 | //2.1 axios请求拦截 13 | instance.interceptors.request.use(config => { 14 | // 一定要返回 15 | return config; 16 | }, err => { 17 | console.log(err); 18 | }); 19 | 20 | // 2.2 axios响应拦截 21 | instance.interceptors.response.use(res => { 22 | return res.data; 23 | }, err => { 24 | console.log(err); 25 | }); 26 | 27 | // 3.发送真正的网络请求 28 | return instance(config); 29 | 30 | } -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailRecommend.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 27 | 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "supermall", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build" 8 | }, 9 | "dependencies": { 10 | "axios": "^0.21.0", 11 | "better-scroll": "^2.0.5", 12 | "core-js": "^3.6.5", 13 | "vue": "^2.6.11", 14 | "vue-lazyload": "^1.3.3", 15 | "vue-router": "^3.4.9", 16 | "vuex": "^3.5.1" 17 | }, 18 | "devDependencies": { 19 | "@vue/cli-plugin-babel": "~4.5.0", 20 | "@vue/cli-service": "~4.5.0", 21 | "vue-template-compiler": "^2.6.11" 22 | }, 23 | "browserslist": [ 24 | "> 1%", 25 | "last 2 versions", 26 | "not dead" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /src/common/mixin.js: -------------------------------------------------------------------------------- 1 | import { debounce } from './utils'; 2 | 3 | export const itemListenerMixin = { 4 | data() { 5 | return { 6 | imgItemListener: null, //控制首页商品图片以及详情页商品推荐列表加载显示的listener 7 | } 8 | }, 9 | mounted() { 10 | const refresh = debounce(this.$refs.scroll.refresh, 500) 11 | this.imgItemListener = ()=>{ 12 | refresh; 13 | } 14 | this.$bus.$on('itemImgLoad', this.imgItemListener); 15 | }, 16 | } 17 | 18 | // 返回顶部图标德混入 19 | export const backTopMixin = { 20 | data(){ 21 | return { 22 | isShowBackTop: false, 23 | } 24 | }, 25 | methods: { 26 | backTopClick(){ 27 | this.$refs.scroll.scrollTo(0,0,500); 28 | }, 29 | }, 30 | } -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailSwiper.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 28 | 29 | 34 | 35 | -------------------------------------------------------------------------------- /src/store/actions.js: -------------------------------------------------------------------------------- 1 | import { 2 | ADD_TO_CART, 3 | ADD_TO_COUNTER 4 | } from './constant'; 5 | 6 | export default { 7 | // 加入购物车 8 | addCart({state, commit}, payload){ 9 | return new Promise((resolve, reject)=>{ 10 | //1.查找之前数组中是否含有该商品 11 | let product = state.cartList.find((item)=> item.iid === payload.iid); 12 | 13 | //2. 判断product,这里涉及深拷贝与浅拷贝 14 | if(product){ 15 | commit(ADD_TO_COUNTER, product); 16 | resolve('成功添加购物车num+1'); 17 | }else { 18 | payload.num = 1; 19 | payload.isSelected = false; 20 | commit(ADD_TO_CART, payload); 21 | resolve('成功添加购物车'); 22 | } 23 | }) 24 | } 25 | } -------------------------------------------------------------------------------- /src/assets/img/tabbar/profile.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/home.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/home_active.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/profile_active.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/content/checkGoodsBtn/CheckGoodsBtn.vue: -------------------------------------------------------------------------------- 1 | 6 | 18 | 19 | 35 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/cart.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/cart_active.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/category/childComps/CategorySideContentItem.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 27 | 28 | 38 | 39 | -------------------------------------------------------------------------------- /src/views/category/childComps/CategorySideContent.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 28 | 36 | 37 | -------------------------------------------------------------------------------- /src/views/home/childComps/RecommendView.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | 24 | 42 | -------------------------------------------------------------------------------- /src/views/home/childComps/HomeSwiper.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /src/network/detail.js: -------------------------------------------------------------------------------- 1 | import { request } from './request'; 2 | 3 | export function getGoodsDetail(iid) { 4 | return request({ 5 | url: '/detail', 6 | params: { 7 | iid 8 | }, 9 | }) 10 | } 11 | 12 | export function getGoodsRecommend(){ 13 | return request({ 14 | url:'/recommend' 15 | }); 16 | } 17 | 18 | export class Goods{ 19 | constructor(itemInfo, columns, services){ 20 | this.iid = itemInfo.iid; 21 | this.title = itemInfo.title; 22 | this.desc = itemInfo.desc; 23 | this.newPrice = itemInfo.price; 24 | this.oldPrice = itemInfo.oldPrice; 25 | this.discount = itemInfo.discountDesc; 26 | this.columns = columns; 27 | this.services = services; 28 | this.realPrice = itemInfo.lowNowPrice; 29 | } 30 | } 31 | 32 | export class Shop{ 33 | constructor(shopInfo){ 34 | this.logo = shopInfo.shopLogo; 35 | this.name = shopInfo.name; 36 | this.fans = shopInfo.cFans; 37 | this.sells = shopInfo.cSells; 38 | this.score = shopInfo.score; 39 | this.goodsCount = shopInfo.cGoods; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/assets/css/base.css: -------------------------------------------------------------------------------- 1 | @import "./normalize.css"; 2 | 3 | /* :root -> 获取根元素html */ 4 | :root { 5 | --color-text: #666; 6 | --color-high-text: #ff5777; 7 | --color-tint: #ff8198; 8 | --color-background: #fff; 9 | --font-size: 14px; 10 | --line-height: 1.5; 11 | } 12 | 13 | *, 14 | *::before { 15 | margin: 0; 16 | padding: 0; 17 | box-sizing: border-box; 18 | } 19 | 20 | body { 21 | font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif; 22 | user-select: none; /* 禁止用户鼠标在页面上选中文字/图片等 */ 23 | -webkit-tap-highlight-color: transparent; /* webkit是苹果浏览器引擎,tap带年底,highlight背景高亮,color颜色,颜色用数值调节*/ 24 | background: var(--color-background); 25 | /* rem vw/vh */ 26 | width: 100vw; 27 | line-height: var(--line-height); 28 | } 29 | 30 | a { 31 | color: var(--color-text); 32 | text-decoration: none; 33 | } 34 | 35 | .clear-fix::after { 36 | clear: both; 37 | content: ''; 38 | display: block; 39 | width: 0; 40 | height: 0; 41 | visibility: hidden; 42 | } 43 | 44 | .clear-fix { 45 | zoom: 1; 46 | } 47 | 48 | .left { 49 | float: left; 50 | } 51 | 52 | .right { 53 | float: right; 54 | } -------------------------------------------------------------------------------- /src/components/common/toast/Toast.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 29 | 30 | 51 | -------------------------------------------------------------------------------- /src/views/cart/childComps/CartList.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 38 | 39 | 53 | 54 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Router from 'vue-router'; 3 | 4 | // 在VUE中路由遇到Error: Avoided redundant navigation to current location:报错显示是路由重复 5 | const originalPush = Router.prototype.push; 6 | Router.prototype.push = function push(location) { 7 | return originalPush.call(this, location).catch(err => err); 8 | } 9 | Vue.use(Router); 10 | 11 | const Home = () => import('@/views/home/Home.vue'); 12 | const Category = () => import('@/views/category/Category.vue'); 13 | const Cart = () => import('@/views/cart/Cart.vue'); 14 | const Profile = () => import('@/views/profile/Profile.vue'); 15 | const Detail = () => import('@/views/detail/Detail.vue'); 16 | 17 | const routes = [ 18 | { 19 | path: '', 20 | redirect: '/home' 21 | }, 22 | { 23 | path: '/home', 24 | component: Home, 25 | }, 26 | { 27 | path: '/category', 28 | component: Category, 29 | }, 30 | { 31 | path: '/cart', 32 | component: Cart, 33 | }, 34 | { 35 | path: '/profile', 36 | component: Profile, 37 | }, 38 | { 39 | path: '/detail/:iid', 40 | component: Detail, 41 | } 42 | ] 43 | const router = new Router({ 44 | routes, 45 | mode: 'history', 46 | }); 47 | 48 | export default router; -------------------------------------------------------------------------------- /src/components/content/tabControl/TabControl.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 37 | 38 | 58 | 59 | -------------------------------------------------------------------------------- /src/components/content/goods/GoodsList.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 46 | 47 | 55 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/category.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/category_active.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailNavBar.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 42 | 43 | 59 | -------------------------------------------------------------------------------- /src/components/content/mainTabBar/MainTabBar.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 38 | -------------------------------------------------------------------------------- /src/views/cart/Cart.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 50 | 51 | 64 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailGoodsInfo.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 45 | 65 | -------------------------------------------------------------------------------- /src/components/common/scroll/Scroll.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 65 | 66 | -------------------------------------------------------------------------------- /src/views/category/childComps/CategorySideBar.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 53 | 69 | 70 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailGoodsParams.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 40 | 41 | 65 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailBottomBar.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 34 | 35 | 82 | -------------------------------------------------------------------------------- /src/components/content/goods/GoodsListItem.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 35 | 77 | 78 | -------------------------------------------------------------------------------- /src/components/common/tabbar/TabBarItem.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 57 | 58 | 71 | 72 | -------------------------------------------------------------------------------- /src/assets/img/common/collect.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/cart/childComps/CartListItem.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 41 | 42 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # supermall 2 | 3 | ### 1.项目简介 4 | > * 该项目为使用vue-cli4搭建的一个前后端分离的商城项目; 5 | > * 使用了Vue[包括混入mixin,过滤器filters相关等],Vuex,Vue-Router,ES6,Axios以及Webpack等前端技术; 6 | > * 主要包含商城首页,详情页,购物车,商品分类,个人中心等模块; 7 | > * 项目涉及vue-lazyload, better-scroll相关运用。 8 | 9 | ### 2. 通过项目能够学到什么 10 | > * 1)Vue,Vuex,Vue-Router,Axios,Webpack的熟悉使用,使用vue-cli脚手架工具初始化Vue项目; 11 | > * 2)组件封装(如轮播图,导航栏的统一封装等),模块化开发,工程化思想; 12 | > * 3)项目开发的基本流程以及调试方法(devtools的使用); 13 | > * 4)学会使用vue-lazyload实现图片懒加载,使用better-scroll实现页面的滚动效果等。 14 | 15 | ### 3. 项目部分截图展示 16 | ###### 1)首页部分 17 | > 主要包括5个部分:顶部导航栏,轮播图,分类,流行推荐,商品部分。 18 | > 19 | ![home1](https://img-blog.csdnimg.cn/2020112510121544.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3MTU1NTgy,size_16,color_FFFFFF,t_70) 20 | ![home2](https://img-blog.csdnimg.cn/20201125101315573.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3MTU1NTgy,size_16,color_FFFFFF,t_70) 21 | 22 | ###### 2)详情页部分 23 | > 主要包括7个部分:商品轮播图,商品信息,商家信息,商品图片,商品参数,商品评论以及推荐商品。 24 | > 25 | ![detail1](https://img-blog.csdnimg.cn/20201125101430211.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3MTU1NTgy,size_16,color_FFFFFF,t_70) 26 | ![detail2](https://img-blog.csdnimg.cn/20201125101455195.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3MTU1NTgy,size_16,color_FFFFFF,t_70) 27 | 28 | ###### 3)购物车部分 29 | > 主要包括2个部分:购物车商品以及结算:涉及的点为商品选中与全选的设置。 30 | > 31 | ![cart1](https://img-blog.csdnimg.cn/20201125101627310.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3MTU1NTgy,size_16,color_FFFFFF,t_70) 32 | ![cart2](https://img-blog.csdnimg.cn/20201125101642320.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3MTU1NTgy,size_16,color_FFFFFF,t_70) 33 | 34 | ###### 4)分类页 35 | > 主要包括左边的主分类与右边的子分类 36 | > 37 | ![cart1](https://img-blog.csdnimg.cn/20201125130205589.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3MTU1NTgy,size_16,color_FFFFFF,t_70) 38 | ![cart2](https://img-blog.csdnimg.cn/20201125130220719.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3MTU1NTgy,size_16,color_FFFFFF,t_70) 39 | 40 | ### 4.项目非常适合Vue实战练手,能够有效提升以及理解对Vue的综合运用以及组件化,模块开发以及工程化思想。 41 | > 如有帮助,请给一个star喔~ 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailBaseInfo.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 36 | 37 | 90 | 91 | -------------------------------------------------------------------------------- /src/views/cart/childComps/CartBottomBar.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 63 | 64 | 93 | -------------------------------------------------------------------------------- /src/views/category/Category.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 73 | 103 | 104 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailCommentInfo.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 80 | 81 | 124 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailShopInfo.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 98 | 99 | 155 | -------------------------------------------------------------------------------- /src/views/home/Home.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 187 | 188 | 224 | -------------------------------------------------------------------------------- /src/views/detail/Detail.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 178 | 179 | 203 | -------------------------------------------------------------------------------- /src/components/common/swiper/Swiper.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 214 | 215 | 245 | 246 | -------------------------------------------------------------------------------- /src/assets/css/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /* Document 4 | ========================================================================== */ 5 | 6 | /** 7 | * 1. Correct the line height in all browsers. 8 | * 2. Prevent adjustments of font size after orientation changes in iOS. 9 | */ 10 | 11 | html { 12 | line-height: 1.15; /* 1 */ 13 | -webkit-text-size-adjust: 100%; /* 2 */ 14 | } 15 | 16 | /* Sections 17 | ========================================================================== */ 18 | 19 | /** 20 | * Remove the margin in all browsers. 21 | */ 22 | 23 | body { 24 | margin: 0; 25 | } 26 | 27 | /** 28 | * Render the `main` element consistently in IE. 29 | */ 30 | 31 | main { 32 | display: block; 33 | } 34 | 35 | /** 36 | * Correct the font size and margin on `h1` elements within `section` and 37 | * `article` contexts in Chrome, Firefox, and Safari. 38 | */ 39 | 40 | h1 { 41 | font-size: 2em; 42 | margin: 0.67em 0; 43 | } 44 | 45 | /* Grouping content 46 | ========================================================================== */ 47 | 48 | /** 49 | * 1. Add the correct box sizing in Firefox. 50 | * 2. Show the overflow in Edge and IE. 51 | */ 52 | 53 | hr { 54 | box-sizing: content-box; /* 1 */ 55 | height: 0; /* 1 */ 56 | overflow: visible; /* 2 */ 57 | } 58 | 59 | /** 60 | * 1. Correct the inheritance and scaling of font size in all browsers. 61 | * 2. Correct the odd `em` font sizing in all browsers. 62 | */ 63 | 64 | pre { 65 | font-family: monospace, monospace; /* 1 */ 66 | font-size: 1em; /* 2 */ 67 | } 68 | 69 | /* Text-level semantics 70 | ========================================================================== */ 71 | 72 | /** 73 | * Remove the gray background on active links in IE 10. 74 | */ 75 | 76 | a { 77 | background-color: transparent; 78 | } 79 | 80 | /** 81 | * 1. Remove the bottom border in Chrome 57- 82 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 83 | */ 84 | 85 | abbr[title] { 86 | border-bottom: none; /* 1 */ 87 | text-decoration: underline; /* 2 */ 88 | text-decoration: underline dotted; /* 2 */ 89 | } 90 | 91 | /** 92 | * Add the correct font weight in Chrome, Edge, and Safari. 93 | */ 94 | 95 | b, 96 | strong { 97 | font-weight: bolder; 98 | } 99 | 100 | /** 101 | * 1. Correct the inheritance and scaling of font size in all browsers. 102 | * 2. Correct the odd `em` font sizing in all browsers. 103 | */ 104 | 105 | code, 106 | kbd, 107 | samp { 108 | font-family: monospace, monospace; /* 1 */ 109 | font-size: 1em; /* 2 */ 110 | } 111 | 112 | /** 113 | * Add the correct font size in all browsers. 114 | */ 115 | 116 | small { 117 | font-size: 80%; 118 | } 119 | 120 | /** 121 | * Prevent `sub` and `sup` elements from affecting the line height in 122 | * all browsers. 123 | */ 124 | 125 | sub, 126 | sup { 127 | font-size: 75%; 128 | line-height: 0; 129 | position: relative; 130 | vertical-align: baseline; 131 | } 132 | 133 | sub { 134 | bottom: -0.25em; 135 | } 136 | 137 | sup { 138 | top: -0.5em; 139 | } 140 | 141 | /* Embedded content 142 | ========================================================================== */ 143 | 144 | /** 145 | * Remove the border on images inside links in IE 10. 146 | */ 147 | 148 | img { 149 | border-style: none; 150 | } 151 | 152 | /* Forms 153 | ========================================================================== */ 154 | 155 | /** 156 | * 1. Change the font styles in all browsers. 157 | * 2. Remove the margin in Firefox and Safari. 158 | */ 159 | 160 | button, 161 | input, 162 | optgroup, 163 | select, 164 | textarea { 165 | font-family: inherit; /* 1 */ 166 | font-size: 100%; /* 1 */ 167 | line-height: 1.15; /* 1 */ 168 | margin: 0; /* 2 */ 169 | } 170 | 171 | /** 172 | * Show the overflow in IE. 173 | * 1. Show the overflow in Edge. 174 | */ 175 | 176 | button, 177 | input { /* 1 */ 178 | overflow: visible; 179 | } 180 | 181 | /** 182 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 183 | * 1. Remove the inheritance of text transform in Firefox. 184 | */ 185 | 186 | button, 187 | select { /* 1 */ 188 | text-transform: none; 189 | } 190 | 191 | /** 192 | * Correct the inability to style clickable types in iOS and Safari. 193 | */ 194 | 195 | button, 196 | [type="button"], 197 | [type="reset"], 198 | [type="submit"] { 199 | -webkit-appearance: button; 200 | } 201 | 202 | /** 203 | * Remove the inner border and padding in Firefox. 204 | */ 205 | 206 | button::-moz-focus-inner, 207 | [type="button"]::-moz-focus-inner, 208 | [type="reset"]::-moz-focus-inner, 209 | [type="submit"]::-moz-focus-inner { 210 | border-style: none; 211 | padding: 0; 212 | } 213 | 214 | /** 215 | * Restore the focus styles unset by the previous rule. 216 | */ 217 | 218 | button:-moz-focusring, 219 | [type="button"]:-moz-focusring, 220 | [type="reset"]:-moz-focusring, 221 | [type="submit"]:-moz-focusring { 222 | outline: 1px dotted ButtonText; 223 | } 224 | 225 | /** 226 | * Correct the padding in Firefox. 227 | */ 228 | 229 | fieldset { 230 | padding: 0.35em 0.75em 0.625em; 231 | } 232 | 233 | /** 234 | * 1. Correct the text wrapping in Edge and IE. 235 | * 2. Correct the color inheritance from `fieldset` elements in IE. 236 | * 3. Remove the padding so developers are not caught out when they zero out 237 | * `fieldset` elements in all browsers. 238 | */ 239 | 240 | legend { 241 | box-sizing: border-box; /* 1 */ 242 | color: inherit; /* 2 */ 243 | display: table; /* 1 */ 244 | max-width: 100%; /* 1 */ 245 | padding: 0; /* 3 */ 246 | white-space: normal; /* 1 */ 247 | } 248 | 249 | /** 250 | * Add the correct vertical alignment in Chrome, Firefox, and Opera. 251 | */ 252 | 253 | progress { 254 | vertical-align: baseline; 255 | } 256 | 257 | /** 258 | * Remove the default vertical scrollbar in IE 10+. 259 | */ 260 | 261 | textarea { 262 | overflow: auto; 263 | } 264 | 265 | /** 266 | * 1. Add the correct box sizing in IE 10. 267 | * 2. Remove the padding in IE 10. 268 | */ 269 | 270 | [type="checkbox"], 271 | [type="radio"] { 272 | box-sizing: border-box; /* 1 */ 273 | padding: 0; /* 2 */ 274 | } 275 | 276 | /** 277 | * Correct the cursor style of increment and decrement buttons in Chrome. 278 | */ 279 | 280 | [type="number"]::-webkit-inner-spin-button, 281 | [type="number"]::-webkit-outer-spin-button { 282 | height: auto; 283 | } 284 | 285 | /** 286 | * 1. Correct the odd appearance in Chrome and Safari. 287 | * 2. Correct the outline style in Safari. 288 | */ 289 | 290 | [type="search"] { 291 | -webkit-appearance: textfield; /* 1 */ 292 | outline-offset: -2px; /* 2 */ 293 | } 294 | 295 | /** 296 | * Remove the inner padding in Chrome and Safari on macOS. 297 | */ 298 | 299 | [type="search"]::-webkit-search-decoration { 300 | -webkit-appearance: none; 301 | } 302 | 303 | /** 304 | * 1. Correct the inability to style clickable types in iOS and Safari. 305 | * 2. Change font properties to `inherit` in Safari. 306 | */ 307 | 308 | ::-webkit-file-upload-button { 309 | -webkit-appearance: button; /* 1 */ 310 | font: inherit; /* 2 */ 311 | } 312 | 313 | /* Interactive 314 | ========================================================================== */ 315 | 316 | /* 317 | * Add the correct display in Edge, IE 10+, and Firefox. 318 | */ 319 | 320 | details { 321 | display: block; 322 | } 323 | 324 | /* 325 | * Add the correct display in all browsers. 326 | */ 327 | 328 | summary { 329 | display: list-item; 330 | } 331 | 332 | /* Misc 333 | ========================================================================== */ 334 | 335 | /** 336 | * Add the correct display in IE 10+. 337 | */ 338 | 339 | template { 340 | display: none; 341 | } 342 | 343 | /** 344 | * Add the correct display in IE 10. 345 | */ 346 | 347 | [hidden] { 348 | display: none; 349 | } --------------------------------------------------------------------------------