码迷,mamicode.com
首页 > 其他好文 > 详细

【珍惜时间】vue2-douban-market

时间:2020-07-15 23:19:03      阅读:64      评论:0      收藏:0      [点我收藏+]

标签:上架   scss   sub   document   can   handle   heat   slot   nat   

老规矩,放下作者大大的github地址:https://github.com/Awheat/vue2-douban-market
接下来我们看看项目效果
技术图片
接下来我们来分析项目

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>db_market</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, minimal-ui">
    <meta content="yes" name="apple-mobile-web-app-capable">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta content="black" name="apple-mobile-web-app-status-bar-style">
    <script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.2/??flexible_css.js,flexible.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

接下来是main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from ‘vue‘
import App from ‘./App‘
import router from ‘./router‘
import store from ‘./store/‘
import VueLazyLoad from ‘vue-lazyload‘

import ‘./assets/css/fonts.css‘

//懒加载的默认图片 
import def_lazy_img from ‘./assets/images/loading.gif‘

//使用懒加载组件
Vue.use(VueLazyLoad,{
	loading: def_lazy_img
})

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: ‘#app‘,
  router,
  store,
  template: ‘<App/>‘,
  components: { App }
})
//app.vue

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>
	export default {
	  name: ‘app‘
	}
</script>
//router.js
import Vue from ‘vue‘
import Router from ‘vue-router‘
import Error from ‘../components/404.vue‘
import Hello from ‘@/components/Hello‘
import Home from ‘@/pages/home/home.vue‘
import Category from ‘@/pages/category/category.vue‘
import Cart from ‘@/pages/cart/cart.vue‘
import My from ‘@/pages/my/my.vue‘
import List from ‘@/pages/list/list.vue‘
import Detail from ‘@/pages/detail/detail.vue‘
import Login from ‘@/pages/login/login.vue‘


Vue.use(Router)

export default new Router({
  linkActiveClass: ‘active‘,
  routes: [
    {
      path: ‘/‘,
      name: ‘Home‘,
      component: Home
    },
    {
    	path:‘/home‘,
    	name:‘Home‘,
    	component: Home
    },
    {
      path:‘/category‘,
      name:‘Category‘,
      component: Category
    },
    {
      path:‘/list/:id‘,
      name:‘List‘,
      component: List
    },
    {
      path:‘/detail/:id‘,
      name:‘Detail‘,
      component: Detail
    },
    {
      path:‘/cart‘,
      name:‘Cart‘,
      component: Cart
    },
    {
      path:‘/my‘,
      name:‘My‘,
      component: My
    },
    {
      path:‘/login‘,
      name:‘Login‘,
      component: Login
    },
    {
      path:‘/404‘,
      name:‘Error‘,
      component: Error
    },
    {
      path: "*",
      redirect: ‘/404‘
    }
  ]
})

技术图片
作者大大们处理值的时候很厉害,把数据放在了vuex中,可以专门看一下
技术图片
技术图片
技术图片
技术图片
接下来看header组件,里面也有对搜索的一个遮罩层的处理,代码很有意思的

//header.vue
<template>
	<div class="db_header">
		<!-- 内容区域 -->
		<div class="db_header_main">
			<!-- logo和搜索icon -->
			<div class="db_logo_box" v-show="!isSearch">
				<div class="db_logo_text">豆瓣市集</div>
				<div class="db_search_icon" v-on:click="onSearch"><i class="fa fa-search"></i></div>
			</div>
			<!-- 搜索块 -->
			<div class="db_search_box" v-show="isSearch">
				<input type="text" name="content" class="ipt_search">
				<span class="btn_search" v-on:click="onSubmit"><i class="fa fa-search"></i></span>
			</div>
		</div>
		<!-- mask遮罩层 -->
		<div class="db_mask" v-show="isSearch" v-on:click="onTapMask"></div>
	</div>
</template>
<script type="text/javascript">
	export default {
		data(){
			return {
				isSearch:false
			}
		},
		methods: {
			onSearch: function(){
				this.isSearch = !this.isSearch;
			},
			onTapMask: function(){
				this.isSearch = !this.isSearch;
			},
			onSubmit: function(){
				let v = document.querySelector(".ipt_search").value;
				alert(v);
			}
		}
	}
</script>
<style scoped>
	.db_header .db_header_main{
		position: relative;
		z-index: 110;
		overflow: hidden;
		background-color: #68cb78;
	}
	/* logo盒子css */
	.db_header .db_logo_box{
		height: 50px;
		line-height: 50px;
	}
	.db_header .db_logo_text{
		display: inline-block;
		color: #fff;
		font-size: .8rem;
		font-weight: 600;
		margin: 0 .5rem;
	}
	.db_header .db_search_icon{
		float: right;
		padding: 0 20px;
		cursor: pointer;
	}
	.db_header .db_search_icon i{
		color: #fff;
		font-size: .7rem;
		vertical-align: sub;
	}
	/* search盒子css */
	.db_header .db_search_box{
		position: relative;
		height: 30px;
		margin:20px 30px;
		padding: 0 20px;
		border: 1px solid #fff;
		border-radius: 30px;
	}
	.db_header .ipt_search{
		width: 100%;
		line-height: 30px;
		border: none;
		color: #fff;
		background-color: transparent;
	}
	.db_header .btn_search{
		position: absolute;
		top: 0;
		right: 0;
		z-index: 10;
		display: block;
		line-height: 30px;
		padding: 0 15px;
		color: #fff;
		font-size: .5rem;
	}
	.db_header .db_mask{
		position: fixed;
    	bottom: 0;
    	left: 0;
    	right: 0;
    	z-index: 100;
    	width: 100%;
    	height: 100%;
    	background-color: rgba(0,0,0,0.5);
	}
</style>

nav里面也挺有意思的,除了是数组循环点击对应的url就跳转到对应的页面之外,还有一个很有意思的就是,vuex监听滚动的距离,而且这个滚动的距离还写在class里面

//nav.vue
<template>
	<div class="db_nav" :class="{fixed:isFixedHeader}">
		<ul>
			<li v-for="item in navItem"><router-link :to="item.url">{{item.text}}</router-link></li>
		</ul>
	</div>
</template>
<script type="text/javascript">
	import {mapState, mapMutations, mapActions} from ‘vuex‘
	export default {
		data() {
			return {
				navItem: [
					{text:"首页",url:"/home"},
					{text:"分类",url:"/category"},
					{text:"购物车",url:"/cart"},
					{text:"我的",url:"/my"},
				]
			}
		},
		computed: {
			//映射State
            ...mapState([
                ‘isFixedHeader‘
            ])
        },
        mounted() {
        	// 监听滚动条
        	window.addEventListener(‘scroll‘,this.handlerScroll);		    
        },
        methods: {
        	// 映射Actions中的handlerScroll方法
        	...mapActions([
			    ‘handlerScroll‘
			])
        }
	}
</script>
<style lang="scss">
	.db_nav{
		height: 43px;
		line-height: 43px;
		border-bottom: 2px solid #3ba94d;
		background-color: #fff;
	}
	.db_nav ul {
		white-space: nowrap;
	    overflow-x: auto;
	    -webkit-overflow-scrolling: touch;
	    display: -o-box;
	    display: -webkit-box;
	    display: -webkit-flex;
	    display: flex;
	    width: 100%;
	}
	.db_nav ul li{
	    display: inline-block;
	    -webkit-box-flex: 1;
	    -webkit-flex: 1;
	    flex: 1;
	    vertical-align: middle;
	    text-align: center;
	}
	.db_nav ul li a.active{
		color:#3ba94d;
	}
	.db_nav ul li a{
		color: #4a4a4a;
		font-size: 15px;
	}
	.db_nav.fixed{
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
	}
</style>

技术图片
技术图片
技术图片

接下来看slider组件
一个普通的轮播组件,不过数据写在vuex中,很有意思

<template>
	<div class="db_swiper">
		<swiper :options="swiperOption">
		  <swiper-slide v-for="slide in sliders">
		  	<a :href="slide.url" target="_blank"><img :src="slide.img"></a>
		  </swiper-slide>
		  <div class="swiper-pagination" slot="pagination"></div>
		</swiper>
	</div>
</template>
<script type="text/javascript">
	import {mapState, mapActions} from ‘vuex‘
	import { swiper, swiperSlide } from ‘vue-awesome-swiper‘

	export default {
		name: ‘carrousel‘,
		//props:[‘sliders‘],
		data() {
		    return {
		      swiperOption: {
		      	initialSlide:1,
		        autoplay: 5000,
		        loop: true,
		        setWrapperSize :true,
		        pagination : ‘.swiper-pagination‘,
		        paginationClickable :true,
		        observeParents:true
		      }
		  	}
		},
		computed: {
			//映射数据
            ...mapState([
                ‘sliders‘
            ])
        },
		mounted() {
		    //获取图片列表
			this.getSliders();
		},
		methods: {
        	...mapActions([
			    ‘getSliders‘
			])
        },
		components: {
		   	swiper,
		    swiperSlide
		}
	}
</script>
<style scoped>
	.db_swiper{
		margin: 2px 0 5px;
	}
	.db_swiper .swiper-slide{
		height: 100px;
		background-color: #e0e0e0;
	}
	.db_swiper .swiper-slide img{
		width: 100%;
		height: 100%;
	}
</style>


技术图片
技术图片
技术图片
技术图片
技术图片
接下来是hot_product组件的

<template>
	<div class="db_hot_product db_products">
		<ul>
			<li v-for="product in hotProducts">
				<div class="pdt_item">
					<a :href="product.url+‘/‘+product.id" class="pdt_img">
						<img :src="product.src" height="300" width="300">
					</a>
					<div class="pdt_detail">
						<h3 class="pdt_title">
							<a :href="product.url">{{product.title}}</a>
						</h3>
						<p class="pdt_price">
							<span class="pdt_new_price">{{product.newPrice}}</span>
							<del class="pdt_old_price">{{product.oldPrice}}</del>
						</p>
					</div>
				</div>
			</li>
		</ul>
	</div>
</template>
<script type="text/javascript">
	export default {
		props:[‘hotProducts‘]
	}
</script>
<style lang="scss"></style>

接下来是hot-shop组件

<template>
	<div class="db_hot_shop" v-infinite-scroll="getHotShops" infinite-scroll-disabled="busy" infinite-scroll-distance="{num}">
		<!-- 一个店铺 -->
		<div class="db_shop_item" v-for="shop in hotShops">
			<!-- 店铺名称和简介 -->
			<div class="shop_info">
				<h3 class="shop_top">
					<a href="" class="shop_img"><img :src="shop.icon" ></a>
					<a href="#" class="shop_name">{{shop.name}}</a>
				</h3>
				<p class="shop_intrduction">{{shop.intrduction}}</p>
			</div>
			<!-- 店铺热门商品 -->
			<div class="shop_product db_products">
				<ul>
					<li v-for="pd in shop.products">
						<div class="pdt_item">
							<a :href="pd.url+‘/‘+pd.id" class="pdt_img">
								<img v-lazy="pd.src" height="300" width="300">
							</a>
							<div class="pdt_detail">
								<h3 class="pdt_title">
									<a :href="pd.url+‘/‘+pd.id">{{pd.title}}</a>
								</h3>
								<p class="pdt_price">
									<span class="pdt_new_price">{{pd.newPrice}}</span>
									<del class="pdt_old_price">{{pd.oldPrice}}</del>
								</p>
							</div>
						</div>
					</li>
				</ul>
			</div>
			<p class="shop_entry"><a :href="shop.url">进入店铺 >></a></p>
		</div>
		
		<!-- 加载更多,没有数据组件 -->
		<loading v-show="isShowLoadingTips"></loading>
		<none v-show="isShowLoadedTips"></none>
	</div>
</template>
<script type="text/javascript">
	import {mapState, mapActions} from ‘vuex‘
	import Loading from ‘../../components/loading.vue‘
	import None from ‘../../components/none.vue‘
	export default {
		computed: {
			//映射State
            ...mapState([
            	‘hotShops‘,
                ‘busy‘,
                ‘isShowLoadingTips‘,
                ‘isShowLoadedTips‘
            ])
        },
		methods: {
		    //获取热门店铺列表
			...mapActions([‘getHotShops‘])
		},
		components: {
			Loading,
			None
		}
	}
</script>
<style lang="scss">
	.db_hot_shop .db_shop_item {
		margin-bottom: 30px;
		-webkit-box-shadow:0 0 1px rgba(0, 0, 0, .1);  
		-moz-box-shadow:0 0 1px rgba(0, 0, 0, .1);  
		box-shadow:0 0 1px rgba(0, 0, 0, .1);  
		background-color: #fff;
	}
	.db_hot_shop .shop_info{
		padding: 25px 10px;
	}
	.db_hot_shop .shop_top{
		height: 30px;
		line-height: 30px;
	}
	.db_hot_shop .shop_img{
		display: block;
		width: 20px;
		height: 30px;
		line-height: 23px;
		float: left;
		margin-right: 10px;
	}
	.db_hot_shop .shop_img img{
		max-width: 100%;
		max-height: 100%;
		vertical-align: middle;
	}
	.db_hot_shop .shop_name{
		display: block;
		width: 70%;
		color: #4a4a4a;
	} 
	.db_hot_shop .shop_intrduction{
		white-space: nowrap;
		text-overflow: ellipsis;
		overflow: hidden;
		color: #9b9b9b;
		font-size: 15px;
	}
	.db_hot_shop .shop_entry{
		text-align: right;
		padding: 0 10px 10px 10px;
		box-sizing: border-box;
	}
	.db_hot_shop .shop_entry a{
		color: #4a4a4a;
		font-size: 15px;
	}
	.loading{
		text-align: center;
		color: #999;
		font-size: 12px;
	}
	.none{
		text-align: center;
		color: #999;
		font-size: 12px;
	}
</style>

这个里面也是有用vuex来保存数据
技术图片
作者大大在详情里面获取的轮播的值就不是写在slider中了,而是直接获取的方法
而且作者大大还额外的做了tab切换的功能,也是很有意思

<template>
	<div class="db_detail">
		<!-- 返回 -->
		<div class="db_detail_back" @click="goBack"><span class="fa fa-chevron-left"></span></div>

		<detail-slider :sliders="sliders"></detail-slider>

		<!-- 名称,价格,其它 -->
		<div class="db_detail_info">
			<div class="title">PISN2016冬季新品  超Q弹加绒打底裤</div>
			<div class="price">
				<span class="now_price">¥199</span>
				<del class="old_price">¥259</del>
			</div>
			<div class="freight">
				<div class="fre_lt">
					<span class="fre_price">运费: ¥8.00</span>
					<span class="fre_tips">非包邮区域</span>
				</div>
				<div class="fre_rt">
					<span class="fa fa-heart-o"></span>
					<span class="fa fa-envelope-o"></span>
				</div>
			</div>
		</div>
		
		<!-- 选择颜色和尺码 -->
		<div class="db_detail_choice">
			<div class="choice_style">
				<label class="choice_title">颜色</label>
				<div class="choice_items">
					<span v-for="(item,index) in colors" :class="{active:index==isColors}" @click="isColors=index">{{item}}</span>
				</div>
			</div>
			<div class="choice_style">
				<label class="choice_title">尺寸</label>
				<div class="choice_items">
					<span v-for="(item,index) in size" :class="{active:index==isSize}" @click="isSize=index">{{item}}</span>
				</div>
			</div>
		</div>
		
		<!-- 选择数量 -->
		<div class="db_detail_num">
			<label class="num_title">数量</label>
			<div class="num_option">
				<span class="minus" :class="{active:number>1}" @click="minus">-</span>
				<input type="number" name="number" class="number" v-model="number">
				<span class="addition" :class="{active:number>0}" @click="addition">+</span>
			</div>
		</div>
		
		<!-- 承诺 -->
		<div class="db_detail_promise">
			<span>豆瓣市集担保</span>
			<span>七天无理由退货</span>
			<span>正品保证</span>
			<span>独立品牌</span>
		</div>
		
		<!-- 选项卡 -->
		<div class="db_detail_tabs">
			<span @click="toggleTabs(‘TabsDetail‘,$event)" data-id="0" :class="{active:0==isActive}">商品详情</span>
			<span @click="toggleTabs(‘TabsRated‘,$event)" data-id="1" :class="{active:1==isActive}">评价<i>2</i></span>
			<span @click="toggleTabs(‘TabsDiscuss‘,$event)" data-id="2" :class="{active:2==isActive}">讨论</span>
		</div>
		
		<!-- tabs内容块-->
		<div class="db_detail_conts">
			<component :is="componentId"></component>
		</div>

		<!-- 固定栏 -->
		<div class="db_fixed_bar">
			<div class="cart"><span class="fa fa-shopping-cart"></span></div>
			<div class="add">加购物车</div>
			<div class="buy">立即购买</div>
		</div>

	</div>
</template>
<script type="text/javascript">
	import axios from ‘axios‘
	import DetailSlider from ‘./detail_slider.vue‘

	import TabsDetail from ‘./tabs_detail.vue‘
	import TabsRated from ‘./tabs_rated.vue‘
	import TabsDiscuss from ‘./tabs_discuss.vue‘

	export default {
		data() {
			return {
				sliders:[],
				isActive:0,
				isColors:0,
				isSize:0,
				number:1,
				colors:[‘白色‘,‘青色‘,‘紫色‘],
				size: [‘S‘,‘M‘,"L","Xl"],
				componentId:‘TabsDetail‘
			}
		},
		mounted(){
			/* 获取详情的轮播图 */
			this.getDetailSlider();
		},
		watch: {
		    // 监听数量的值
			number: function(val,oldVal){
				if(val<0){
					this.number = 1;
				}else{
					this.number = parseInt(val);
				}
			}
		},
		methods: {
		    //获取图片数据
			getDetailSlider(){
				axios.get(‘/mock/detail/detail_slider.json‘).then((response)=>{
					this.sliders = response.data.list;
				}).catch(function(error){
					console.log(‘请求slider数据:‘+error);
				});
			},
			//tab选项卡的切换
			toggleTabs(componentId,e) {
				this.isActive = e.target.getAttribute("data-id");
				this.componentId = componentId;
			},
			//数量减函数
			minus() {
				if(this.number>0){
					this.number--;
				}
			},
			//数量加函数
			addition() {
				if(isNaN(this.number)){
					this.number = 0;
				}
				this.number++;
			},
			//返回
			goBack(){
				this.$router.go(-1);
			}
		},
		components: {
			DetailSlider,
			TabsDetail,
			TabsRated,
			TabsDiscuss
		}
	}
</script>
<style scoped>
	.db_detail{
		padding-bottom: 100px;
	}
	.db_detail .db_detail_back{
		position: fixed;
		top: 10px;
		left: 10px;
		z-index: 100000;
		width: 30px;
		height: 30px;
		line-height: 30px;
		text-align: center;
		color: #ccc;
		font-size: 14px;
		background-color: rgba(255,255,255,.5);
		border-radius: 100%;
	}
	.db_detail .db_detail_info{
		padding: 15px;
		font-size: 16px;
		background-color: #fff;
		border-bottom: 1px solid #f0f0f0;
	}
	.db_detail .db_detail_info .title{
	}
	.db_detail .db_detail_info .price{
		margin: 10px 0;
	}
	.db_detail .db_detail_info .now_price{
		color: #e17c72;
		font-weight: 600;
	}
	.db_detail .db_detail_info .old_price{
		color: #ccc;
	}
	.db_detail .db_detail_info .freight{
		height: 20px;
		line-height: 20px;
	}
	.db_detail .db_detail_info .fre_lt{
		max-width: 80%;
		float: left;
		font-size: 14px;
		white-space: nowrap;
		text-overflow: ellipsis;
		overflow: hidden;
	}
	.db_detail .db_detail_info .fre_rt{
		float: right;
	}
	.db_detail .db_detail_info .fre_tips{
		color: #e17c72;
	}
	.db_detail .db_detail_info .fa-heart-o{
		padding-right: 10px;
		color: #e17c72;
	}
	.db_detail .db_detail_info .fa-envelope-o{
		color:#68cb78;
	}

	
	.db_detail .db_detail_choice{
		padding: 15px;
		border-bottom: 1px solid #f0f0f0;
	}
	.db_detail .db_detail_choice .choice_style{
		display: -webkit-box;
		display: -webkit-flex;
		display: box;
		display: flex;
		line-height: 25px;
		padding: 5px 0;
	}
	.db_detail .db_detail_choice .choice_title{
		display: inline-block;
		width: 50px;
		color: #9b9b9b;
		font-size: 14px;
	}
	.db_detail .db_detail_choice .choice_items{
		-webkit-box-flex: 1;
		-webkit-flex: 1;
		box-flex: 1;
		flex: 1;
		font-size: 0;
	}
	.db_detail .choice_items span{
		display: inline-block;
		width: 70px;
		height: 25px;
		text-align: center;
		margin: 0 5px;
		color: #fff;
		font-size: 14px;
		border-radius: 20px;
		background-color: #ccc;
	}
	.db_detail .choice_items span.active{
		color: #fff;
		background-color: #68cb78;
	}

	.db_detail .db_detail_num{
		display: -webkit-box;
		display: -webkit-flex;
		display: box;
		display: flex;
		height: 25px;
		line-height: 25px;
		padding: 15px;
		border-bottom: 1px solid #f0f0f0;
	}	
	.db_detail .db_detail_num .num_title{
		display: inline-block;
		width: 50px;
		color: #9b9b9b;
		font-size: 16px;
	}
	.db_detail .db_detail_num .num_option{
		-webkit-box-flex: 1;
		-webkit-flex: 1;
		box-flex: 1;
		flex: 1;
		font-size: 0;
		margin-left: 5px;
	}
	.db_detail .num_option .minus,
	.db_detail .num_option .addition{
		display: inline-block;
		width: 25px;
		height: 25px;
		line-height: 25px;
		text-align: center;
		color: #fff;
		font-size: 24px;
		font-weight: 600;
		background-color: #ccc;
		border-radius: 25px;
	}
	.db_detail .num_option .number{
		display: inline-block;
		width: 70px;
		height: 25px;
		line-height: 25px;
		color: #333;
		font-size: 16px;
		text-align: center;
		margin: 0 10px;
		border: none;
		vertical-align: top;
		background-color: #ccc;
		border-radius: 50px;
	}
	.db_detail .num_option span.active{
		background-color: #68cb78;
	}

	.db_detail_promise {
		padding: 5px 15px;
		text-align: center;
		font-size: 0;
	}
	.db_detail_promise span{
		color: #9b9b9b;
		font-size: 12px;
		padding: 0 5px;
	}
	.db_detail_promise span:first-of-type{
		border-right: 1px solid #ccc;
	}
	.db_detail_promise span:nth-of-type(3){
		border-right: 1px solid #ccc;
		border-left: 1px solid #ccc;
	}

	
	.db_detail_tabs {
		display: -webkit-box;
		display: -webkit-flex;
		display: box;
		display: flex;
		height:40px;
		margin-top: 30px;
		border-bottom: 2px solid #e17c72;
	}
	.db_detail_tabs span{
		-webkit-box-flex: 1;
		-webkit-flex: 1;
		box-flex: 1;
		flex: 1;
		line-height: 40px;
		text-align: center;
		color: #666;
		font-size: 16px;
	}
	.db_detail_tabs span.active{
		color: #e17c72;
	}
	.db_detail_tabs span i{
		font-style: normal;
	}

	.db_fixed_bar{
		position: fixed;
		left: 0;
		bottom: 0;
		display: -webkit-box;
		display: -webkit-flex;
		display: box;
		display: flex;
		width: 100%;
		height: 50px;
		background-color: #f8f8fe;
	}
	.db_fixed_bar > div{
		-webkit-box-flex: 1;
		-webkit-flex: 1;
		box-flex: 1;
		flex: 1;
		line-height: 50px;
		text-align: center;
		color: #fff;
		font-size: 14px;
	}
	.db_fixed_bar .cart{
		color: #9d9d9d;
		font-size: 16px;
	}
	.db_fixed_bar .add {
		background-color: #eba887;
	}
	.db_fixed_bar .buy{
		background-color: #e17c72;
	}
</style>

技术图片
技术图片
很有意思,tab切换的组件是直接引入的
技术图片

<template>
	<div class="tabs_detail">
		<img src="http://p1.bpimg.com/587986/649b4ff9a029dbb3.jpg">
		<img src="http://p1.bpimg.com/587986/c5d8d2c850c5cc92.jpg">
		<img src="http://p1.bpimg.com/587986/12e168a53d8b1390.jpg">
		<img src="http://p1.bpimg.com/587986/4aa678607eb830c0.jpg">
		<img src="http://p1.bpimg.com/587986/c7ad269e33e3978f.jpg">
		<img src="http://p1.bpimg.com/587986/8cf8a0478c1bb5f7.jpg">
		<img src="http://p1.bpimg.com/587986/7d53301336e9b995.jpg">
		<img src="http://p1.bpimg.com/587986/cefa54f9c5d03776.jpg">
		<img src="http://p1.bpimg.com/587986/5624606500e540ca.jpg">
		<img src="http://p1.bpimg.com/587986/5008ba25e806446c.jpg">
		<img src="http://p1.bpimg.com/587986/68ce77370073e517.jpg">
		<img src="http://p1.bpimg.com/587986/23fc150f3b39e7ea.jpg">
		<img src="http://p1.bpimg.com/587986/6a0de86396c71324.jpg">
		<img src="http://p1.bpimg.com/587986/08115d10186e5bb9.jpg">
		<div class="bottom_bar">
			<a href="#" class="explain">购物说明</a>
			<a href="#" class="help">帮助</a>
			<a href="#" class="concat">联系豆瓣</a>
		</div>
		<div class="bottom_link">逛逛<a href="#">豆瓣市集</a></div>
	</div>
</template>

<style scoped>
	.tabs_detail img{
		display: block;
		max-width: 100%;
	}
	.tabs_detail .bottom_bar{
		padding: 5px 15px;
		border-bottom: 1px solid #f0f0f0;
	}
	.tabs_detail .bottom_bar a{
		color: #9b9b9b;
		font-size: 14px;
	}
	.tabs_detail .bottom_bar .explain{
		padding-right: 5px;
		border-right: 1px solid #9b9b9b;
	}
	.tabs_detail .bottom_bar .concat{
		float: right;
	}
	.tabs_detail .bottom_link{
		text-align: center;
		padding: 25px 0;
		font-size: 14px;
	}
	.tabs_detail .bottom_link a{
		color: #3ba94d;
		margin-left: 2px;
	}
</style>
<template>
	<div class="tabs_rated">
		<!-- 评论结果 -->
		<div class="rated_result">
			<div class="overall">
				<span class="overall_lt">综合平分<i class="red">4.2</i></span>
				<span class="overall_rt">
					<i class="fa fa-star red"></i>
					<i class="fa fa-star red"></i>
					<i class="fa fa-star red"></i>
					<i class="fa fa-star red"></i>
					<i class="fa fa-star red"></i>
				</span>
			</div>
			<div class="ruler">
				<span>很好<i class="red">7</i></span>
				<span>较好<i class="red">3</i></span>
				<span>一般<i class="red">2</i></span>
				<span>差<i class="red">1</i></span>
				<span>极差<i class="red">0</i></span>
			</div>
		</div>
		<!-- 评论列表 -->
		<div class="db_comments">
			<!-- 一条评论 -->
			<div class="comment_item">
				<div class="comment_infos">
					<img src="http://p1.bpimg.com/587986/c7ad269e33e3978f.jpg" class="u_photo">
					<span class="u_name">张三</span>
					<span class="u_time">2016-07-07 16:23:44</span>
					<span class="u_rated">
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
					</span>
				</div>
				<div class="comment_text">
					买的亚麻短裤,感觉板型、做工都还可以的,上身也比较舒适,就是不知道水洗后怎样~
					总体感觉性价比挺高
				</div>
			</div>
			<!-- 一条评论 -->
			<div class="comment_item">
				<div class="comment_infos">
					<img src="http://p1.bpimg.com/587986/c7ad269e33e3978f.jpg" class="u_photo">
					<span class="u_name">张三</span>
					<span class="u_time">2016-07-07 16:23:44</span>
					<span class="u_rated">
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
					</span>
				</div>
				<div class="comment_text">
					买的亚麻短裤,感觉板型、做工都还可以的,上身也比较舒适,就是不知道水洗后怎样~
					总体感觉性价比挺高
				</div>
			</div>
			<!-- 一条评论 -->
			<div class="comment_item">
				<div class="comment_infos">
					<img src="http://p1.bpimg.com/587986/c7ad269e33e3978f.jpg" class="u_photo">
					<span class="u_name">张三</span>
					<span class="u_time">2016-07-07 16:23:44</span>
					<span class="u_rated">
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
					</span>
				</div>
				<div class="comment_text">
					买的亚麻短裤,感觉板型、做工都还可以的,上身也比较舒适,就是不知道水洗后怎样~
					总体感觉性价比挺高
				</div>
			</div>
			<!-- 一条评论 -->
			<div class="comment_item">
				<div class="comment_infos">
					<img src="http://p1.bpimg.com/587986/c7ad269e33e3978f.jpg" class="u_photo">
					<span class="u_name">张三</span>
					<span class="u_time">2016-07-07 16:23:44</span>
					<span class="u_rated">
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
					</span>
				</div>
				<div class="comment_text">
					买的亚麻短裤,感觉板型、做工都还可以的,上身也比较舒适,就是不知道水洗后怎样~
					总体感觉性价比挺高
				</div>
			</div>
			<!-- 一条评论 -->
			<div class="comment_item">
				<div class="comment_infos">
					<img src="http://p1.bpimg.com/587986/c7ad269e33e3978f.jpg" class="u_photo">
					<span class="u_name">张三</span>
					<span class="u_time">2016-07-07 16:23:44</span>
					<span class="u_rated">
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
					</span>
				</div>
				<div class="comment_text">
					买的亚麻短裤,感觉板型、做工都还可以的,上身也比较舒适,就是不知道水洗后怎样~
					总体感觉性价比挺高
				</div>
				<div class="comment_picture">
					<img src="http://p1.bpimg.com/587986/649b4ff9a029dbb3.jpg">
					<img src="http://p1.bpimg.com/587986/c5d8d2c850c5cc92.jpg">
					<img src="http://p1.bpimg.com/587986/12e168a53d8b1390.jpg">
					<img src="http://p1.bpimg.com/587986/4aa678607eb830c0.jpg">
				</div>
			</div>
			<!-- 一条评论 -->
			<div class="comment_item">
				<div class="comment_infos">
					<img src="http://p1.bpimg.com/587986/c7ad269e33e3978f.jpg" class="u_photo">
					<span class="u_name">张三</span>
					<span class="u_time">2016-07-07 16:23:44</span>
					<span class="u_rated">
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
					</span>
				</div>
				<div class="comment_text">
					买的亚麻短裤,感觉板型、做工都还可以的,上身也比较舒适,就是不知道水洗后怎样~
					总体感觉性价比挺高
				</div>
				<div class="comment_picture">
					<img src="http://p1.bpimg.com/587986/649b4ff9a029dbb3.jpg">
					<img src="http://p1.bpimg.com/587986/c5d8d2c850c5cc92.jpg">
					<img src="http://p1.bpimg.com/587986/12e168a53d8b1390.jpg">
					<img src="http://p1.bpimg.com/587986/4aa678607eb830c0.jpg">
				</div>
			</div>
			<!-- 一条评论 -->
			<div class="comment_item">
				<div class="comment_infos">
					<img src="http://p1.bpimg.com/587986/c7ad269e33e3978f.jpg" class="u_photo">
					<span class="u_name">张三</span>
					<span class="u_time">2016-07-07 16:23:44</span>
					<span class="u_rated">
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
					</span>
				</div>
				<div class="comment_text">
					买的亚麻短裤,感觉板型、做工都还可以的,上身也比较舒适,就是不知道水洗后怎样~
					总体感觉性价比挺高
				</div>
				<div class="comment_picture">
					<img src="http://p1.bpimg.com/587986/649b4ff9a029dbb3.jpg">
					<img src="http://p1.bpimg.com/587986/c5d8d2c850c5cc92.jpg">
					<img src="http://p1.bpimg.com/587986/12e168a53d8b1390.jpg">
					<img src="http://p1.bpimg.com/587986/4aa678607eb830c0.jpg">
				</div>
			</div>
			<!-- 一条评论 -->
			<div class="comment_item">
				<div class="comment_infos">
					<img src="http://p1.bpimg.com/587986/c7ad269e33e3978f.jpg" class="u_photo">
					<span class="u_name">张三</span>
					<span class="u_time">2016-07-07 16:23:44</span>
					<span class="u_rated">
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
						<i class="fa fa-star red"></i>
					</span>
				</div>
				<div class="comment_text">
					买的亚麻短裤,感觉板型、做工都还可以的,上身也比较舒适,就是不知道水洗后怎样~
					总体感觉性价比挺高
				</div>
				<div class="comment_picture">
					<img src="http://p1.bpimg.com/587986/649b4ff9a029dbb3.jpg">
					<img src="http://p1.bpimg.com/587986/c5d8d2c850c5cc92.jpg">
					<img src="http://p1.bpimg.com/587986/12e168a53d8b1390.jpg">
					<img src="http://p1.bpimg.com/587986/4aa678607eb830c0.jpg">
				</div>
			</div>
		</div>
	</div>
</template>
<style type="text/css">
	.red{color: #eba887;}
	.tabs_rated i{
		font-style: normal;
	}
	.tabs_rated .rated_result{
		text-align: center;
		padding: 15px 0;
		border-bottom: 1px solid #f0f0f0;
	}
	.tabs_rated .rated_result .overall{
		font-size: 14px;
		margin-bottom: 10px;
	}
	.tabs_rated .rated_result .overall_lt{
		color: #9d9d9d;
	}
	.tabs_rated .rated_result .ruler{
		color: #ccc;
	}
	.tabs_rated .rated_result .ruler .red{
		padding: 0 5px 0 2px;
	}
	
	/* 评论列表 */
	.db_comments {}
	.db_comments .comment_item {
		padding: 15px;
		border-bottom: 1px solid #f0f0f0;
		box-sizing: border-box;
	}
	.db_comments .comment_item .comment_infos{
		height: 20px;
		line-height: 20px;
	}
	.db_comments .comment_item .u_photo{
		display: inline-block;
		width: 20px;
		height: 20px;
		border-radius: 20px;
		vertical-align: top;
	}
	.db_comments .comment_item .u_name{
		color: #9d9d9d;
		font-size: 14px;
	}
	.db_comments .comment_item .u_time{
		color: #ccc;
	}
	.db_comments .comment_item .comment_text{
		color: #4a4a4a;
		font-size: 14px;
		line-height: 20px;
		padding: 10px 0 10px 25px;
		box-sizing: border-box;
	}
	.db_comments .comment_item .comment_picture{
		font-size: 0;
		padding-left: 25px;
		box-sizing: border-box;
	}
	.db_comments .comment_item .comment_picture img{
		display:inline-block;
		width: 48px;
		height: 48px;
		margin-right: 10px;
		border: 1px solid #f0f0f0;
	}
</style>

技术图片

<template>
	<!-- 讨论列表 -->
	<div class="db_comments">
		<!-- 一条讨论 -->
		<div class="comment_item">
			<div class="comment_infos">
				<img src="http://p1.bpimg.com/587986/c7ad269e33e3978f.jpg" class="u_photo">
				<span class="u_name">张三</span>
				<span class="u_time">2016-07-07 16:23:44</span>
			</div>
			<div class="comment_text">180偏瘦的人买XL的还是XXL的?</div>
		</div>

		<!-- 一条讨论 -->
		<div class="comment_item">
			<div class="comment_infos">
				<img src="http://p1.bpimg.com/587986/c7ad269e33e3978f.jpg" class="u_photo">
				<span class="u_name">李四</span>
				<span class="u_time">2016-07-07 16:23:44</span>
			</div>
			<div class="comment_text">可不可以防水防火防电</div>
		</div>

		<!-- 一条讨论 -->
		<div class="comment_item">
			<div class="comment_infos">
				<img src="http://p1.bpimg.com/587986/c7ad269e33e3978f.jpg" class="u_photo">
				<span class="u_name">王五</span>
				<span class="u_time">2016-07-07 16:23:44</span>
			</div>
			<div class="comment_text">过几年会升值吗?</div>
		</div>
	</div>
</template>
<style type="text/css">
	.red{color: #eba887;}
	/* 评论列表 */
	.db_comments {}
	.db_comments .comment_item {
		padding: 15px;
		border-bottom: 1px solid #f0f0f0;
		box-sizing: border-box;
	}
	.db_comments .comment_item .comment_infos{
		height: 20px;
		line-height: 20px;
	}
	.db_comments .comment_item .u_photo{
		display: inline-block;
		width: 20px;
		height: 20px;
		border-radius: 20px;
		vertical-align: top;
	}
	.db_comments .comment_item .u_name{
		color: #9d9d9d;
		font-size: 14px;
	}
	.db_comments .comment_item .u_time{
		color: #ccc;
	}
	.db_comments .comment_item .comment_text{
		color: #4a4a4a;
		font-size: 14px;
		line-height: 20px;
		padding: 10px 0 10px 25px;
		box-sizing: border-box;
	}
	.db_comments .comment_item .comment_picture{
		font-size: 0;
		padding-left: 25px;
		box-sizing: border-box;
	}
	.db_comments .comment_item .comment_picture img{
		display:inline-block;
		width: 48px;
		height: 48px;
		margin-right: 10px;
		border: 1px solid #f0f0f0;
	}
</style>

技术图片
category页面和我想象的一样,就是比较容易的实现方法

//category.vue
<template>
	<div class="category">
		<header-bar></header-bar>
		<nav-bar></nav-bar>
		<div class="category_list">
			<ul>
				<li v-for="cty in categorys">
					<router-link :to="cty.url" :class="cty.class_name">{{cty.text}}</router-link>
				</li>
			</ul>
		</div>
	</div>
</template>


<script type="text/javascript">

	import HeaderBar from ‘../../components/header.vue‘
	import NavBar from ‘../../components/nav.vue‘
	export default {
		data() {
			return {
				categorys:[
					{text:"饮食",url:"/list/1",class_name:"red"},
					{text:"服装",url:"/list/2",class_name:"blue"},
					{text:"配饰",url:"/list/3",class_name:"purple"},
					{text:"包袋",url:"/list/4",class_name:"sky"},
					{text:"鞋靴",url:"/list/5",class_name:"yellow"},
					{text:"美容护肤",url:"/list/6",class_name:"pink"},
					{text:"家居",url:"/list/7",class_name:"grass"},
					{text:"时间",url:"/list/8",class_name:"green"},
					{text:"3C数码",url:"/list/9",class_name:"red"}
				]
			}
		},
		components: {
			HeaderBar,
			NavBar
		}
	}
</script>
<style scoped>
	.category_list{
		font-size: 0;
		padding: 10px 5px;
		text-align: center;
		box-sizing: border-box;
	}
	.category_list ul li{
		display: inline-block;
		width: 30%;
		height: 60px;
		margin: 0 3px 10px 3px;
	}
	.category_list a{
		display: block;
		line-height: 60px;
		text-align: center;
		color: #4a4a4a;
		font-size: 14px;
		border-radius: 5px;
	}
	.category_list .red{
		background-color: #ffb2bb;
	}
	.category_list .blue{
		background-color: #89b7ec;
	}
	.category_list .purple{
		background-color: #c2a0e0;
	}
	.category_list .sky{
		background-color: #b2e6ff;
	}
	.category_list .yellow{
		background-color: #e6e7a4;
	}
	.category_list .pink{
		background-color: #e0a0d1;
	}
	.category_list .grass{
		background-color: #b2ffc5;
	}
	.category_list .green{
		background-color: #ffb2bb;
	}
</style>

技术图片
cat页面

<template>
	<div class="cart">
		<header-bar></header-bar>
		<nav-bar></nav-bar>
		<div class="login_false">
			<div class="login_false">还未登录,请使用豆瓣账号登录</div>
			<div class="login_entry">
				<p class="login_tip2">登录豆瓣账号后,可以进行订单查询,使用优惠券</p>
				<a href="#/login" class="btn_login">登录</a>
				<p class="btn_regist">没有豆瓣账号?<a href="#">注册</a></p>
			</div>
			<div class="anonymous">
				<p>使用匿名购买,则可以点击以下链接查询订单</p>
				<p><a href="#">查询订单</a></p>
			</div>
		</div>
	</div>
</template>

<script type="text/javascript">

	import HeaderBar from ‘../../components/header.vue‘
	import NavBar from ‘../../components/nav.vue‘

	export default {
		components: {
			HeaderBar,
			NavBar
		}
	}
</script>
<style scoped>
	.login_false .login_false{
		text-align: center;
		padding: 1rem 0;
		border-bottom: 1px solid #9d9d9d;
		background-color: #f8f8fe;
	}
	.login_false .login_entry{
		padding: 20px;
		text-align: center;
		border-bottom: 1px solid #9d9d9d;
		background-color: #fff;
	}
	.login_false .login_entry .login_tip2{
		color: #4a4a4a;
	}
	.login_false .login_entry .btn_login{
		display: block;
		padding: 10px 0;
		text-align: center;
		margin: 15px 0;
		color: #fff;
		font-size: 14px;
		border-radius: 5px;
		background-color: #68cb78;
	}
	.login_false .login_entry .btn_regist{
		color: #9d9d9d;
	}
	.login_false .login_entry .btn_regist a{
		color: #68cb78;
	}
	.login_false .anonymous{
		text-align: center;
		color: #9b9b9b;
		padding-top: 2rem;
	}
	.login_false .anonymous p{
		padding: 5px 0;
	}
	.login_false .anonymous a{
		color: #68cb78;
	}
</style>

技术图片
接下来是Login页面
没有做什么特别的处理

<template>
	<div class="db_login">
		<div class="db_login_top"><a href="javascript:void(0);" class="cancel" @click="goBack">取消</a>登录豆瓣</div>
		<div class="db_login_form">
			<form action="#" method="post">
				<p class="form_item"><input type="text" name="username" placeholder="邮箱/手机号/用户名"></p>
				<p class="form_item"><input type="password" name="pasword" placeholder="密码"></p>
				<p class="form_btn"><button type="submit">登录</button></p>
			</form>
		</div>
		<div class="login_other">使用其它方式登录 & 找回密码</div>
		<div class="regist_download">
			<a href="#">注册豆瓣</a><a href="#">下载豆瓣App</a>
		</div>
	</div>
</template>
<script type="text/javascript">
	export default {
		methods: {
			goBack(){
				this.$router.go(-1);
			}
		}
	}
</script>
<style scoped>
	.db_login {
		font-size: 16px;
	}
	.db_login .db_login_top{
		position: relative;
		height: 50px;
		line-height: 50px;
		text-align: center;
		color: #333;
		font-weight: 600;
		border-bottom: 1px solid #f0f0f0;
	}
	.db_login .db_login_top .cancel{
		position: absolute;
		top: 0;
		left: 0;
		display: block;
		padding: 0 20px;
		color: #42bd56;
		font-size: 14px;
		font-weight: normal;
	}
	.db_login .db_login_form{
		padding: 0 15px;
		margin: 25px 0 5px;
	}
	.db_login .db_login_form .form_item{
		height: 45px;
		line-height: 45px;
		padding: 0 10px;
		margin-bottom: -1px;
		box-sizing: border-box;
		border: 1px solid #e0e0e0;
	}
	.db_login .form_item:nth-of-type(1){
		border-top-left-radius: 3px;
		border-top-right-radius: 3px;
	}
	.db_login .form_item:nth-of-type(2){
		border-bottom-left-radius: 3px;
		border-bottom-right-radius: 3px;
	}
	.db_login .db_login_form input{
		border: none;
	}
	.db_login .db_login_form .form_btn{
		margin-top: 10px;
	}
	.db_login .form_btn button{
		-webkit-appearance: none;
		-moz-appearance: none;
		appearance: none;
		border: 0;
		width: 100%;
		height: 40px;
		line-height: 40px;
		text-align: center;
		color: #fff;
		font-size: 14px;
		background-color: #17AA52;
		border-radius: 3px;
	}
	.db_login .login_other{
		color: #9d9d9d;
		text-align: center;
		margin-top: 15px;
	}
	.db_login .regist_download{
		text-align: center;
		margin-top: 40px;
	}
	.db_login .regist_download a{
		color: #42bd56;
		font-size: 14px;
		margin: 0 10px;
	}
</style>

技术图片
my页面中比较有意思的是一个下拉的时候自动加载更多数据的功能,是用到了这个组件vue-infinite-scroll,这里的数据也是直接用axios请求的
不是用的vuex

//my.vue
<template>
	<div class="my">
		<header-bar></header-bar>
		<nav-bar></nav-bar>
		<div class="db_hot_product db_products" v-infinite-scroll="loadMore" infinite-scroll-disabled="busy" infinite-scroll-distance="10">
			<ul>
				<li v-for="product in productList">
					<div class="pdt_item">
						<a :href="product.url+‘/‘+product.id" class="pdt_img">
							<img v-lazy="product.src" height="300" width="300">
						</a>
						<div class="pdt_detail">
							<h3 class="pdt_title">
								<a :href="product.url">{{product.title}}</a>
							</h3>
							<p class="pdt_price">
								<span class="pdt_new_price">{{product.newPrice}}</span>
								<del class="pdt_old_price">{{product.oldPrice}}</del>
							</p>
						</div>
					</div>
				</li>
			</ul>
			<div class="none" v-show="tips">已没有更多数据...</div>
		</div>

		<div class="loading" v-show="loading"></div>
	</div>
</template>

<script type="text/javascript">
	import Vue from ‘vue‘
	import axios from ‘axios‘
	import infiniteScroll from ‘vue-infinite-scroll‘
	import TEST_IMAGE_SRC from‘../../assets/images/test_hot_product.jpg‘;
	import HeaderBar from ‘../../components/header.vue‘
	import NavBar from ‘../../components/nav.vue‘

	Vue.use(infiniteScroll);
	export default {
		data() {
			return {
				productList: [],
				data: [],
				tips:false,
				loading:false,
				num:10,
    			busy: false
			}
		},
		mounted() {
			
		},		
		methods: {
			getData(){
				axios.get(‘/mock/products/products.json‘).then((response)=>{
					var result = response.data.list.slice(this.num-10,this.num);
					console.log(result);
					if(result.length !== 0){
						this.loading = false;
						for(let i in result){
							this.productList.push({
								id:result[i].id,
								src:result[i].src,
							    url:result[i].url,
							    title:result[i].title,
							    newPrice: result[i].newPrice,
							    oldPrice: result[i].oldPrice
							});
						}
						this.busy = false;
						this.num+=10;
					}else{
						this.busy = true;
						this.tips = true;
						this.loading = false;
					}	
				})
			},
		    loadMore() {
		      	this.busy = true;
		      	this.loading = true;
		      	setTimeout(() => {
			        this.getData();
			    }, 1000);
		      	
		    }
		},
		components: {
			HeaderBar,
			NavBar
		}
	}
</script>
<style scoped>
	.loading{
		position: fixed;
		top: 50%;
		left: 50%;
		z-index: 10000;
		width: 16px;
		height: 16px;
		margin: -16px 0 0 -16px;
		background: url(../../assets/images/loading.gif);
	}
	.none{
		text-align: center;
		padding: 10px 0;
		color: #999;
		font-size: 12px;
	}
</style>

技术图片
我们可以看一下list页面
list页面也是有加载更多的功能,不过这个里面的加载更多就是写在vuex中的
技术图片
技术图片
技术图片
技术图片
下面的值也是写在vuex中的

<template>
	<div class="db_list">
		<list-header></list-header>
		<list-nav></list-nav>
		<div class="db_list_options">
			<div class="items">
				<a href="#" class="active">总和排序 <i class="fa fa-arrow-down"></i></a>
				<a href="#">上架时间 <i class="fa fa-arrow-down"></i></a>
				<a href="#">价格 <i class="fa fa-arrow-down"></i></a>
				<a href="#">喜欢数 <i class="fa fa-arrow-down"></i></a>
			</div>
		</div>

		<div class="db_products" v-infinite-scroll="getProducts" infinite-scroll-disabled="busy" infinite-scroll-distance="10">
			<ul>
				<li v-for="product in products">
					<div class="pdt_item">
						<a :href="product.url+‘/‘+product.id" class="pdt_img">
							<img v-lazy="product.src" height="300" width="300">
							<i class="fa fa-heart-o" v-on:click="onHeart($event)"></i>
						</a>
						<div class="pdt_detail">
							<h3 class="pdt_title">
								<a :href="product.url">{{product.title}}</a>
							</h3>
							<p class="pdt_price">
								<span class="pdt_new_price">{{product.newPrice}}</span>
								<del class="pdt_old_price">{{product.oldPrice}}</del>
							</p>
						</div>
					</div>
				</li>
			</ul>
			<!-- 加载更多,没有数据组件 -->
			<loading v-show="isShowLoadingTips"></loading>
			<none v-show="isShowLoadedTips"></none>
		</div>
	</div>
</template>
<script type="text/javascript">
	import {mapState, mapActions} from ‘vuex‘
	import ListHeader from ‘./list_header.vue‘
	import ListNav from ‘./list_nav.vue‘
	import Loading from ‘../../components/loading.vue‘
	import None from ‘../../components/none.vue‘

	export default {
		data() {
			return {
				flag: true
			}
		},
		computed: {
			//映射State
            ...mapState([
            	‘products‘,
                ‘busy‘,
                ‘isShowLoadingTips‘,
                ‘isShowLoadedTips‘
            ])
        },
		methods: {
			...mapActions([‘getProducts‘]),
		    onHeart: function(e){
		    	if(this.flag){
		    		e.target.className="fa fa-heart";
		    		this.flag = false;
		    	}else{
		    		e.target.className="fa fa-heart-o";
		    		this.flag = true;
		    	}
		    	e.preventDefault();
		    }
		},
		components: {
			ListHeader,
			ListNav,
			Loading,
			None
		}
	}
</script>
<style scoped>
	.db_list_options {
		height: 40px;
		line-height: 40px;
		padding: 0 15px;
	}
	.db_list_options .items{
		width: 100%;
		display: flex;
		display: box;
		display: -webkit-box;
		flex-wrap:nowrap;
		justify-content: center;
	}
	.db_list_options .items a{
		display: block;
		flex: 1;
		box-flex: 1;
		-webkit-box-flex: 1;
		text-align: center;
		color: #ccc;
	}
	.db_list_options .items a.active{
		color: #f67;
	}
	.db_products .pdt_img{
		position: relative;
	}
	.db_products .pdt_img .fa{
		position: absolute;
		top: 10px;
		right: 10px;
		color: #e17c72;
		font-size: 16px;
	}
</style>

看一下list页面中的list-header组件
这种状态值同class联合在一起的控制显示隐藏的很有意思

<template>
	<div class="list_header">
		<a href="#/home" class="btn_index">首页</a>
		<div class="list_category" v-on:click="chooseCategory">{{currenSelect.text}} <i class="fa fa-angle-down"></i></div>
		<div class="category_box" v-bind:class="{slide_down:isShow}">
			<ul>
				<li v-for="(item, index) in categorys" :data-id="index" v-on:click="onSelect($event)" v-bind:class="[index==currenSelect.id?‘active‘:‘‘]">{{item.text}}</li>
			</ul>
		</div>
		<div class="mask" v-show="isShow" v-on:click="onMask"></div>
	</div>
</template>
<script type="text/javascript">
	export default {
		data(){
			return {
				isShow: false,
				currenSelect:{
					id:0,
					text:‘饮食‘
				},
				categorys:[
					{id:0,text:‘饮食‘},
					{id:1,text:‘配饰‘},
					{id:2,text:‘鞋靴‘},
					{id:3,text:‘美容护肤‘},
					{id:4,text:‘家居‘},
					{id:5,text:‘时间‘},
					{id:6,text:‘3C数码‘},
					{id:7,text:‘情侣装‘},
					{id:8,text:‘母婴儿童‘},
					{id:9,text:‘内衣‘},
					{id:10,text:‘运动户外‘},
					{id:11,text:‘玩具‘},
					{id:12,text:‘汽车用品‘},
					{id:12,text:‘艺术品‘},
					{id:12,text:‘图书‘}
				]
			}
		},
		methods: {
		    // 显示分类菜单函数
			chooseCategory(){
				this.isShow = true;
			},
			// 点击Mask消失函数
			onMask(){
				this.isShow = false;
			},
			// 选择商品分类
			onSelect(e) {
				let that = e.target;
				this.currenSelect.id = that.getAttribute(‘data-id‘);
				this.currenSelect.text = that.innerText;
				this.isShow = false;
			}
		}
	}
</script>
<style scoped>
	.list_header {
		position: relative;
		height: 40px;
		line-height: 40px;
		font-size: 16px;
		background-color: #fff;
	}
	.list_header .btn_index {
		position: absolute;
		top: 0;
		left: 0;
		display: block;
		padding: 0 15px;
		text-align: center;
		color: #999;
	}
	.list_header .list_category{
		width: auto;
		margin: 0 auto;
		text-align: center;
		color: #3ba94d;
	}
	.list_header .category_box{
		position: fixed;
    	top: -50%;
    	left: 50%;
    	z-index: 110;
    	width: 240px;
    	height: 320px;
    	padding: 10px 0;
    	margin: -160px 0 0 -120px;
    	border-radius: 3px;
    	background-color: #fff;
    	box-shadow: 0 0 6px #ccc;
    	overflow: hidden;
    	transition: top .5s ease 0s;
	}
	.list_header .slide_down{
		top: 50%;
	}
	.list_header .category_box ul{
		width: 250px;
		height: 100%;
		overflow-y: auto;
		-webkit-overflow-scrolling: touch;
	}
	.list_header .category_box ul li{
		text-align: center;
		color: #666;
		font-size: 14px;
	}
	.list_header .category_box ul li.active{
		background-color: #f0f0f0;
	}
	.list_header .mask{
		position: fixed;
    	bottom: 0;
    	left: 0;
    	right: 0;
    	z-index: 100;
    	width: 100%;
    	height: 100%;
    	background-color: rgba(0,0,0,0.5);
	}
</style>

list-nav组件其实没有什么特别的,不过css中有个比较特别的就是让页面可以滚动

<template>
	<div class="list_nav">
		<ul>
			<li class="cur"><a href="#">全部</a></li>
			<li><a href="#">男上装</a></li>
			<li><a href="#">男下装</a></li>
			<li><a href="#">裙装</a></li>
			<li><a href="#">女套装</a></li>
			<li><a href="#">女上装</a></li>
			<li><a href="#">女下装</a></li>
			<li><a href="#">裙装</a></li>
			<li><a href="#">女套装</a></li>
			<li><a href="#">女上装</a></li>
			<li><a href="#">女下装</a></li>
		</ul>
	</div>
</template>
<style scoped>
	.list_nav{
		height: 40px;
		overflow: hidden;
		background-color: #68cb78;
	}
	.list_nav ul{
		width: auto;
		height: 60px;
		white-space: nowrap;
		overflow-x: auto;
		-webkit-overflow-scrolling: touch;
	}
	.list_nav ul li{
		display: inline-block;
		padding: 0 15px;
		line-height: 40px;
	}
	.list_nav ul li.cur a{
		color: #fff;
	}
	.list_nav ul li a{
		color: #333;
		font-size: 14px;
	}
</style>

作者大大的项目很有意思,可以学到很多东西呢,向大家推荐推荐哇

【珍惜时间】vue2-douban-market

标签:上架   scss   sub   document   can   handle   heat   slot   nat   

原文地址:https://www.cnblogs.com/smart-girl/p/13307160.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!