c'c

大城市里の小女人 提交于 2020-04-29 10:03:39
  1. 引入css

    1. normalize.css
    2. base.css,在里面引用normalize.css
    3. 在app.vue引用base.css
  2. 创建页面home,category,cart,profile

  3. router配置

  4. tabbaritem

    难点在于判断item是否被点击

    isActive(){
     	return this.$route.path.indexOf('this.link')!=-1
    }
    
    点击后文字更改样式
    activeStyle(){
    	return this.isActive?{'color':'#333'}:{}
    }
    

Request.js

import axios from 'axios'

export function request(config) {
    // 1.创建axios的实例
    const instance = axios.create({
        baseURL: 'http://152.136.185.210:8000/api/h8',
        timeout: 5000
    })

    // 2.axios的拦截器
    // 2.1.请求拦截的作用
    instance.interceptors.request.use(config => {
        return config
    }, err => {
        // console.log(err);
    })

    // 2.2.响应拦截
    instance.interceptors.response.use(res => {
        return res.data
    }, err => {
        console.log(err);
    })

    // 3.发送真正的网络请求
    return instance(config)
}

Home.js

import {request} from "./request";

export function getHomeMultidata() {
    return request({
        url: '/home/multidata'
    })
}

export function getHomeGoods(type, page) {
    return request({
        url: '/home/data',
        params: {
            type,
            page
        }
    })
}

在home.vue引用

    import {getHomeMultidata} from "network/home";

swiper

需要banners和recommend数据

//请求数据并保存
created() {
            getHomeMultidata().then(res => {
                this.banners=res.data.banner.list
                this.recommends=res.data.recommend.list
            });
        }
//把数据传到swiper组件
                <home-swiper :banners="banners"></home-swiper>

homeswiper组件

<template>
    <swiper ref="swiper"
    v-if="banners.length">
        <swiper-item v-for="(item,index) in banners" :key="index">
            <a :href="item.link">
                <img :src="item.image" alt="">
            </a>
        </swiper-item>
    </swiper>
</template>

<script>
    import {Swiper, SwiperItem} from 'common/swiper'

    export default {
        name: "HomeSwiper",
        components: {
            Swiper,
            SwiperItem
        }, props: {
            banners: {
                type: Array,
                default: []
            }
        },
        methods:{
            stopTimer() {
                this.$refs.swiper.stopTimer()
            },
            startTimer() {
                if (this.$refs.swiper) {
                    this.$refs.swiper.startTimer()
                }
            }
        }

    }
</script>

<style scoped>

</style>

recommendView

需要recommend数据

<template>
    <div class="recommend">
        <div v-for="item in recommends" class="recommed-item">
            <a href="item.link">
                <img :src="item.image" alt="">
                <div>{{item.title}}</div>
            </a>
        </div>
    </div>
</template>

<script>
    export default {
        name: "RecommendView",
        props: {
            recommends: {
                type: Array,
                default: []
            }
        }
    }
</script>

<style scoped>
    .recommend {
        display: flex;
        justify-content: space-around;
        text-align: center;
        padding-bottom: 20px;
        border-bottom: 10px solid #eee;
    }

    .recommed-item img {
        margin-top: 10px;
        margin-bottom: 5px;
        height: 70px;
        width: 70px;
        flex: 1;
    }
</style>

featureView

<template>
    <div class="feature">
        <a href="https://act.mogujie.com/zzlx67">
            <img src="~assets/img/home/recommend_bg.jpg" alt="">
        </a>
    </div>
</template>

<script>
    export default {
        name: "FeatureView"
    }
</script>

<style scoped>
.feature img{
    width: 100%;
}
</style>

tabControl

需要titles数据

class:index==currentindex

Click:currentindex==index

<template>
    <div class="tab-control">
        <div v-for="(item,index) in titles" class="tab-control-item"
             :class="{active:index==currentIndex}"
             @click="itemClick(index)">
            <span>{{item}}</span>
        </div>
    </div>
</template>

<script>
    export default {
        name: "TabControl",
        props: {
            titles: {
                type: Array,
                default: []
            }
        },
        data() {
            return {
                currentIndex: 0
            }
        },
        methods: {
            itemClick(index) {
                this.currentIndex = index
            }
        }
    }
</script>

<style scoped>
    .active span{
        color: #ff8198;
        border-bottom: 2px solid #ff8198;
    }


    .tab-control {
        display: flex;
        text-align: center;
    }

    .tab-control-item {
        height: 40px;
        line-height: 40px;
        flex: 1;
    }

    .tab-control-item span {
        font-size: 17px;
        padding: 5px;

    }
</style>

商品展示

需要流行,精选数据

  1. 请求数据
export function getHomeGoods(type, page) {
    return request({
        url: '/home/data',
        params: {
            type,
            page
        }
    })
}

把请求方法写在methods,create调用methiods方法

import {getHomeMultidata, getHomeGoods} from "network/home";
created() {
            this.getHomeMultidata()

            this.getHomeGoods('pop')
            this.getHomeGoods('new')
            this.getHomeGoods('sell')
        }, methods: {
            getHomeGoods(type) {
                const page = this.goods[type].page + 1
                getHomeGoods(type, page).then(res => {
                    console.log(res)
                    this.goods[type].list.push(...res.data.list)
                    this.goods[type].page += 1
                })
            },
            getHomeMultidata() {
                getHomeMultidata().then(res => {
                    console.log(res)
                    this.banners = res.data.banner.list
                    this.recommends = res.data.recommend.list
                })
            }

        }

goodsLIst

需要goods['type'].list数据

flex-wrap:wrap

<template>
    <div class="goods-list">
        <goods-list-item v-for="item in goodsList" :goodsItem="item"></goods-list-item>
    </div>
</template>

<script>
    import GoodsListItem from "./GoodsListItem";

    export default {
        name: "GoodsList",
        components: {
            GoodsListItem
        }, props: {
            goodsList: {
                type: Array,
                default: []
            }
        }

    }
</script>

<style scoped>
.goods-list {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-around;
    padding: 2px;
}
</style>

goodsListItem

设置宽度,才能用flex-wrap

<template>
    <div class="goods-item">
        <img :src="goodsItem.show.img" alt="">
        <div class="goods-info">
            <p>{{goodsItem.title}}</p>
            <span class="price">{{goodsItem.price}}</span>
            <span class="collect">{{goodsItem.cfav}}</span>
        </div>

    </div>
</template>

<script>
    export default {
        name: "GoodsListItem",
        props: {
            goodsItem: {
                type: Object,
                default() {
                    return {}
                }
            }
        }
    }
</script>

<style scoped>
    .goods-item {
        padding-bottom: 40px;
        position: relative;

        width: 48%;
    }

    .goods-item img {
        width: 100%;
        border-radius: 5px;
    }

    .goods-info {
        font-size: 12px;
        position: absolute;
        bottom: 5px;
        left: 0;
        right: 0;
        overflow: hidden;
        text-align: center;
    }

    .goods-info p {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        margin-bottom: 3px;
    }

    .goods-info .price {
        color: var(--color-high-text);
        margin-right: 20px;
    }

    .goods-info .collect {
        position: relative;
    }

    .goods-info .collect::before {
        content: '';
        position: absolute;
        left: -15px;
        top: -1px;
        width: 14px;
        height: 14px;
        background: url("~assets/img/common/collect.svg") 0 0/14px 14px;
    }
</style>

tabControl切换数据

点击切换流行 ,新款的数据

在scroll组件要设置clck:true,不然div等标签监听不到点击

tabcontrol发送自定义事件,并传到Home当前index,Home然后根据index来switch选择是pop还是new

<tab-control :titles="['流行','新款','精选']" @tabClick="tabClick"></tab-control>
<goods-list :goodsList="showGoods"></goods-list>
tabClick(index) {
    switch (index) {
        case 0:
            this.currentTab = 'pop';
            break
        case 1:
            this.currentTab = 'new';
            break
        case 2:
            this.currentTab = 'sell';
            break
    }
}
computed:{
            showGoods() {
                return this.goods[this.currentTab].list
            }
        }

better-scroll

要在mount里创建对象

mounted(){
	this.scroll = new BScroll(document.querySelector('.wrapper'),{
	probeTybe:3,
  pullUpload:true,
    
	})
  this.scroll.on('scroll',(position) => {
    console.log(position)
  })
  this.scroll.on('pullingUp',() =>{
    console.log('上拉加载更多')
    
    setTimeOut(() =>{
      scroll.finishPullUp()
    },2000)
  })
}

Wrapper要有固定高度,它的子标签只能有一个

注意它的父标签的高度

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    .content {
      height: 200px;
      background-color: red;
      overflow: hidden;
    }
  </style>
</head>
<body>

<div>
  <div class="content">
    <ul>
      <button class="btn">按钮</button>
      <li>列表数据1</li>
      <li>列表数据2</li>
      <li>列表数据3</li>
      <li>列表数据4</li>
      <li>列表数据5</li>
      <li>列表数据6</li>
      <li>列表数据7</li>
      <li>列表数据8</li>
      <li>列表数据9</li>
      <li>列表数据10</li>
      <li>列表数据11</li>
      <li>列表数据12</li>
      <li>列表数据13</li>
      <li>列表数据14</li>
      <li>列表数据15</li>
      <li>列表数据16</li>
      <li>列表数据17</li>
      <li>列表数据18</li>
      <li>列表数据19</li>
      <li>列表数据20</li>
      <li>列表数据21</li>
      <li>列表数据22</li>
      <li>列表数据23</li>
      <li>列表数据24</li>
      <li>列表数据25</li>
      <li>列表数据26</li>
      <li>列表数据27</li>
      <li>列表数据28</li>
      <li>列表数据29</li>
      <li>列表数据30</li>
      <li>列表数据31</li>
      <li>列表数据32</li>
      <li>列表数据33</li>
      <li>列表数据34</li>
      <li>列表数据35</li>
      <li>列表数据36</li>
      <li>列表数据37</li>
      <li>列表数据38</li>
      <li>列表数据39</li>
      <li>列表数据40</li>
      <li>列表数据41</li>
      <li>列表数据42</li>
      <li>列表数据43</li>

    </ul>
  </div>
</div>

<script src="./bscroll.js"></script>
<script>
  // 默认情况下BScroll是不可以实时的监听滚动位置
  // probe 侦测
  // 0,1都是不侦测实时的位置
  // 2: 在手指滚动的过程中侦测, 手指离开后的惯性滚动过程中不侦测.
  // 3: 只要是滚动, 都侦测.
  const bscroll = new BScroll(document.querySelector('.content'), {
    probeType: 3,
    click: true,
    pullUpLoad: true
  })

  bscroll.on('scroll', (position) => {
    // console.log(position);
  })    

  bscroll.on('pullingUp', () => {
    console.log('上拉加载更多');
    // 发送网络请求, 请求更多页的数据

    // 等数据请求完成, 并且将新的数据展示出来后
    setTimeout(() => {
      bscroll.finishPullUp()
    }, 2000)
  })

  document.querySelector('.btn').addEventListener('click', function () {
    console.log('------');
  })
</script>
</body>
</html>

封装better-scroll

<template>
    <div ref="wrapper">
        <div class="content">
            <slot></slot>
        </div>
    </div>
</template>

<script>
    import bscroll from 'better-scroll'
    export default {
        name: "Scroll",
        components:{
            scroll
        },
        data() {
            return {
                scroll:null,
            }
        },
        mounted() {
            this.scroll=new bscroll(this.$refs.wrapper,{
                probeType:3,
                pullUpLoad:true
            })
            this.scroll.on('scroll',(position) => {
                console.log(position);
            })
        }
    }
</script>

<style scoped>

</style>

backTop

//注意直接监听组件的原生事件,要有native
<back-top @click.native="backTopClick"></back-top>

实时判断是否显示backtop

先把scroll组件里的position信息发到home,因为在home里可以方便的管理backtop是否显示

this.scroll.on('scroll', (position) => {
                this.$emit('scroll',position)
            })
<scroll class="content" ref="wrapper" :probe-type="3" @scroll="contentScroll">

注意,position是负数,要把它换成正数计算

contentScroll(position) {
                console.log(position)
                this.isShowBackTop = -position.y > 1000
            }
<back-top @click.native="backTopClick" v-show="isShowBackTop"></back-top>

上拉加载更多

this.scroll.on('pullingUp',() => {
    this.$emit('pullingUp');
})
 <scroll class="content" ref="wrapper" :probe-type="3" @scroll="contentScroll"
                :pull-up-load="true"
                @pullingUp="loadMore">
//没事做可以封装一下这个方法
finishPullUp() {
    this.scroll.finishPullUp();
}
loadMore() {
    this.getHomeGoods(this.currentTab);
    this.$refs.wrapper.finishPullUp();

}

可滚动区域的问题

问题原因:没请求到图片时把可滚动区域计算好了,请求完图片,可滚动区域就不够了

解决办法:监听图片加载完就重新计算可滚动区域

Vue.prototype.$bus = new Vue()
imgLoad() {
                this.$bus.$emit('imgLoad')
            }
this.$bus.$on('imgLoad', () => {
    this.$refs.wrapper.refresh()
})

可能出现的问题:

问题1:加载完图片,scroll对象还没创建好,但是home就调用scroll的refresh方法,导致报错

解决办法1:

调用方法前判断对象是否为空

this.scroll && this.scroll.refresh()

解决办法2:

也有可能是create里面拿不到this.$refs.wrapper,那么就去mounted里调用方法

mounted() {
    this.$bus.$on('imgLoad', () => {
        this.$refs.wrapper.refresh()
    })
}

防抖函数提升性能

debounce(func, delay) {
    let timer = null;
    return function (...args) {
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => {
            func.apply(...args)
        }, delay);
    }
}
mounted() {
    const refresh = this.debounce(this.$refs.wrapper.refresh, 50)
    this.$bus.$on('imgLoad', () => {
        refresh()
    })
}

没事做可以抽取一下debounce

export function mounted() {
    const refresh = this.debounce(this.$refs.wrapper.refresh, 50)
    this.$bus.$on('imgLoad', () => {
        refresh()
    })
}
import {debounce} from "common/util";

tabControl吸顶效果

解决思路:

拿到tabcontrol的offsettop

存在的问题:图片没加载完,拿到offsettop可能是错的

console.log(this.$refs.tabControl.$el.offsetTop);

监听图片加载完,在发出自定义事件,

data() {
    return {
        isImgLoad:false
    }
},
//这样只发送一次事件
imgLoad() {
                if (!this.isImgLoad) {
                    this.$emit('imgLoad');
                    this.isImgLoad=true
                }
            }
imgLoad() {
    this.tabControlOffsetTop = this.$refs.tabControl.$el.offsetTop;
}
contentScroll(position) {
    //判断显示返回顶部的组件
    this.isShowBackTop = -position.y > 1000
    //判断是否吸顶
    this.isTabFixed = -position.y > this.tabControlOffsetTop
    console.log(this.isTabFixed)
},
<tab-control :titles="['流行','新款','精选']" @tabClick="tabClick" ref="tabControl"
             :class="{fixed : isTabFixed}"></tab-control>
//data数据
tabControlOffsetTop: 0,
isTabFixed: false,
.fixed {
    position: fixed;
    top: 44px;
    left: 0;
    right: 0;
}

存在的问题:这么做没有吸顶,因为和betterscroll的滚动逻辑冲突了

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!