-
引入cssjavascript
- normalize.css
- base.css,在裏面引用normalize.css
- 在app.vue引用base.css
-
建立頁面home,category,cart,profilecss
-
router配置html
-
tabbaritemvue
難點在於判斷item是否被點擊java
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數據ios
//請求數據並保存 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數據axios
<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數據api
class:index==currentindex網絡
Click:currentindex==indexapp
<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>
商品展現
須要流行,精選數據
- 請求數據
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的滾動邏輯衝突了