項目需求分析
1 項目前期准備工作
1. cli搭建項目
2.css樣式導入 公共資源圖片等的導入
<script>
module.exports = {
configureWebpack: {
resolve: {
alias: {
'assets': '@/assets',
'common': '@/common',
'components': '@/components',
'network': '@/network',
'views': '@/views',
}
}
}
</script>
<script>
root = true
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
</script>
2 底部導航欄封裝
3 Home 頂部導航欄封裝(因我在其他的頁面中也有這個組件)
4 Home組件首頁輪播圖組件導入
5 安裝axios 網絡封裝
<script>
import axios from 'axios'
export function request(config) {
// 1.創建axios的實例
const instance = axios.create({
baseURL: 'http://123.207.32.32:8000/api/h8',
//baseURL: 'http://106.54.54.237:8000/api/v1,
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)
}
6 在組件剛一創建的時候就發送網絡請求,在created生命周期函數進行網絡請求
輪播圖數據展示/推薦數據展示/流行數據展示(feature)
7 Tab'Cont'rol業務分析 因為在其他頁面還有使用 應該是在業務組件中
8 請求首頁goods數據
點擊3個不同的按鈕請求不同的數據,首頁列表數據請求保存
goods: {
'pop': {page: 1, list:[]},
'new': {page: 1, list:[]},
'sell': {page: 1, list:[]}
}
//發送HomeGoods商品列表數據 需要進行參數傳遞
export function getHomeGoods(type, page) {
return request({
url: '/home/data',
params: {
type,
page
}
})
}
//請求數據
getHomeGoods('pop',1).then(res => {
console.log(res);
})
8.1如何點擊不同tabControl 請求不同的數據
// 2 請求homeGoods商品數據
this.getHomeGoods('pop')
this.getHomeGoods('new')
this.getHomeGoods('sell')
getHomeGoods(type) {
const page = this.goods[type].page + 1
getHomeGoods(type,page).then(res => {
// console.log(res.data.list);
this.goods[type].list.push(
8.2對商品列表分析,和業務相關 而不是公共組件了
然后把數據傳遞到goodsList goodsListItem
9 引入better-scroll 解決在移動端滾動卡頓問題
需求: 為了減少對better-sroll的依賴,對better-scroll 進行封裝 而且在多數頁面需要用到,在公共組件進行創建創建,將引用插件進行封裝成一個組件,那里需要進行導入這個組件即可,后期維護也方便,邏輯也i清晰
better-scroll安裝:
1. 終端通過npm安裝: npm install better-scroll --save
<template>
<div class="wrapper" ref="wrapper">
<div class="content">
<slot></slot>
</div>
</div>
</template>
<script>
import BScroll from 'better-scroll'
export default {
data() {
return {
scroll: null
}
},
props: {
probeType: {
type: Number,
default() {
return 0
}
}
},
mounted() {
//1 創建BScroll實力對象
this.scroll = new BScroll(this.$refs.wrapper, {
click: true,
probeType: this.probeType //默認為不觸發scroll滾動事件,那個頁面需要進行傳值即可,這樣性能也大大提高
})
滾動原理:
10 點擊backTop按鈕返回Home頂部
需求:
需求分析:
-
首先該功能會在頁面滾動某個臨界值進行顯示或隱藏,其次不會隨着頁面滾動而滾動,所以簡單方法進行fixed 固定定位
-
對頁面需要進行實時監聽滾動位置
-
該需求是在Home 首頁組件進行監聽,也就是需要對backTop這個組件進行監聽
下面進行代碼實現:
-
新建BackTop組件,引入一張箭頭圖片,如下
<template>
<div class="back-top" >
<img src="~assets/img/common/top.png" alt="">
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
.back-top {
position: fixed;
right: 8px;
bottom: 50px;
}
.back-top img {
width: 42px;
height: 42px;
}
</style> -
在Home首頁組件導入並注冊:(需要注意的是這個組件是不需要隨着滾動的)
-
對這個組件進行事件點擊監聽 --------組件監聽需要用到事件修飾符native(這里也可以在backTop組件內部進行點擊事件,然后把這個事件發送出來在進行監聽,這樣做不過相對繁瑣,還多寫了代碼)

然后通過ref拿到scroll這個組件調用scrollTo()這個方法
backTopClick() {
// console.log(this.$refs.scroll.scroll);
// this.$refs.scroll.scroll.scrollTo(0, 0, 400);
this.$refs.scroll.scrollTo(0, 0, 400);
}
//scrollTo(x, y, time, easing)
//參數:
//{Number} x 橫軸坐標(單位 px)
//{Number} y 縱軸坐標(單位 px)
//{Number} time 滾動動畫執行的時長(單位 ms)
//{Object} easing 緩動函數,一般不建議修改,如果想修改,參考源碼中的 ease.js 里的寫法
//返回值:無
//作用:滾動到指定的位置,引用:https://ustbhuangyi.github.io/better-scroll/doc/zh-hans/api.html#scrolltox-y-time-easing//this.$refs.scroll.scroll.scrollTo(0, 0, 400)
//此代碼不方便閱讀,對奇進行封裝,把插件scrollTo()封裝到組件scrollTo中 看代碼吧 這樣更清楚
4.對Home頁面滾動進行實時監聽,而我們封裝的BScroll滾動插件是scroll這個組件,這里需要在scroll組件進行監聽,然后把這個事件發送出了
mounted() {
//1 創建BScroll實力對象
this.scroll = new BScroll(this.$refs.wrapper, {
click: true,
probeType: this.probeType
}),
//發送事件監聽事件
this.scroll.on('scroll', (position) => {
// console.log(position);
this.$emit('scroll',position)
})
}
然后在首頁接受這個事件,設置一個變量控制backTop顯示隱藏
contentScroll(position) {
console.log(position);
this.isShow = -position.y > 1300 ? true : false
}
目前代碼效果:
11 點擊商品列表進入商品詳情頁
分析: 每個商品都有不同id,所以在點擊每個goodslistitem,我們需要拿到這個唯一的商品id,去后台接口請求對應的商品數據,然后在進行展示,而且從home也跳轉到詳情頁,我們使用路由就可以
1 對goodslistitem進行點擊事件,並將商品id傳過去
goodsItemClick() {
console.log('111',this.goodsitem.iid);
this.$router.push('/detail/'+ this.goodsitem.iid)
}
//路由跳轉傳參 可以有2種方式 1 動態路由 2 query方式
goodsItemClick() {
// console.log('-----',this.goodsitem.iid)
//動態路由
this.$router.push('/detail/'+ this.goodsitem.iid)
//query方式
this.$router.push({
path: '/detail',
query: {
iid: this.goodsitem.iid
}
})
}
//路由配置方式也不一樣
{
path: '/detail/:iid', //動態路引
component: Detail
},
{
path: '/detail', //query方式
component: Detail
}
//獲取iid方式
this.iid = this.$route.params.iid
this.iid = this.$route.query.iid
// 另外在url中顯示也有差異 如下
2 拿到iid在network請求數據,為了方便后期維護 閱讀,我們單獨新建詳情頁網絡請求 dedtail.js
import {request} from './request'
export function getDetail(iid) {
return request({
url: '/detail',
params: {
iid
}
})
}
之后在Detail組件剛一創建出來created生命周期函數進行網絡請求
12 上拉加載更多
在封裝好的 BScroll 中 調用上拉加載更多事件,然后把這個事件發送出來,然后在home頁 執行並調用finishPullUp()
//上拉加載更多
this.scroll.on('pullingUp',() => {
// console.log('上拉加載更多');
this.$emit('pullingUp')
// this.scroll.finishPullUp()
})
home頁進行監聽
//上拉加載更多
pullUpClick() {
// console.log('上拉加載');
this.getHomeGoods(this.currentType)
this.$refs.scroll.finishPullUp()
},
13 解決首頁 詳情頁 滾動卡頓問題
-
分析:
-
主要原因是圖片加載影響 better-scroll計算可滾動區域問題,不能滾動的問題主要是因為圖片加載完成后,這個時候better-scroll得到可滾動區域height,沒有刷新,所導致
-
我們對每一張加載圖片進行監聽 ,只要有一張圖片你加載完成,我們就重新計算一次Bscroll的高度
-
如何監聽圖片加載完成
-
原生js監聽 img.load = () => {}
-
Vue提供的加載方式 @load=() => {}
-
-
然后調用better-scroll的refresh()
//refresh()
//參數:無
//返回值:無
//作用:重新計算 better-scroll,當 DOM 結構發生變化的時候務必要調用確保滾動的效果正常。
-
-
這里涉及到非父子組件事件通信,我們可以使用Vuex或者事件總線 這里我們先使用事件總線
-
1 事件總線使用方法:
-
main.js入口文件 掛載到Vue原型實例上,全局任何地方都可以使用
-
Vue.prototype.$bus = new Vue()
-
發送事件
-
this.$bus.$emit('itemImageLoad',params)// 事件函數, 參數
-
接收事件
-
this.$bus.$on("", callback) // 事件函數 回調函數 一般是組件運行階段,mounted函數中執行
-
取消事件
-
this.$bus.$off("", callback) // 事件函數 回調函數 取消事件是組件是否有keep-alive 有選擇deactivated 否destroyed中
-
-
2 使用Vuex進行非父子組件通信
-
先創建·1一個變量,對這個變量植進行watch監聽,每加載一張圖片,變量植發生改變
-
14 實現詳情頁上下聯動聯動效果,點擊對應標題滾動到對應的位置和內容滾動顯示正確標題
-
效果圖:
-
-
點擊標題跳轉到對應位置
-
每給標題對應一個值,只要我們拿到這個值,在點擊標題的時候,調用scrollTo就可以滾 動到對應位置,所以我們新建一個數組,來保存offsetTop
-
首先對詳情頁 標題 進行監聽
-
獲取 詳情頁 所有組件的offsetTop
-
如何獲取 不同組件 的offsetTop
-
首先我們會想到在mounted中獲取offsetTop,然而獲取的值完全不對,甚至出現了undefined
-
mounted() {
console.log('-----')
this.themeTops = [];
this.themeTops.push(0);
this.themeTops.push(this.$refs.paramsinfo.$el.offsetTop);
this.themeTops.push(this.$refs.commentinfo.$el.offsetTop);
this.themeTops.push(this.$refs.recommend.$el.offsetTop);
console.log(this.themeTops);
},
//[0, undefined, 498, 626, __ob__: Observer] -
值獲取不正確,首先想到的是圖片影響,之前我們有對圖片的加載進行監聽,圖片加載完成后,我們再獲取offsetTop值
-
//對詳情頁圖片監聽
detailImageLoad() {
//獲取參數 評論 推薦的offsetTop值
this.themeTops = [];
this.themeTops.push(0);
this.themeTops.push(this.$refs.paramsinfo.$el.offsetTop);
this.themeTops.push(this.$refs.commentinfo.$el.offsetTop);
this.themeTops.push(this.$refs.recommend.$el.offsetTop);
console.log(this.themeTops);
this.$refs.scroll.refresh();
},
// 打印結果 [0, 9289, 10031, 10180, __ob__: Observer] -
然后調用scrollTo方法
-
titleClick(index) {
// console.log(index);
this.$refs.scroll.scrollTo(0, -this.themeTops[index], 300)
},
-
-
-
內容滾動顯示正確標題
-
分析: 我們需要實時對頁面滾動進行監聽 ,在better-scroll中把scroll這個事件發送出來,我們在Detail進行接受這個事件
-
通過獲取到posiiton.y 和之前獲取到 this.themeTops這個數組中4個值進行比較 然后動態改變標題
-
-
14 Vue原生上下聯動或左右聯動效果
-
上下聯動或左右聯動效果非常常見 但是我們平時大多使用封裝好的UI工具庫,直接按需導入安裝,這里我們不使用插件和UI
-
這里我們主要簡單建立三個組件
-
-
1 點擊ShopTitles中小titles 讓活躍title顯示背景顏色 其他不變,這個相對簡單
-
2 點擊不同title讓右邊的Shop組件跳轉到不同位置
-
1 首先要監聽SHop組件的滾動,其次調用JS原生滾動方法 scroll
-
2 對Shop組件添加滾動事件 需要注意的是 addEventListener第三個參數為true ,
-
3 父元素 overflow不能是hidden,而是scroll,要不然子元素滾動不了 (當然子元素內容高度高於父元素高度)
-
//父組件
<template>
<div class="category">
<div class="nav-bar" >
<div class="nav"> 我是頂部的商品展示區域</div>
</div>
<shop-titles :titles="titles" @titleClick="titleClick" ref="titles"/>
<shop ref="shop" @shopOpsitons="shopOpsitons" />
</div>
</template>
<script>
import Shop from 'components/common/shop/Shop'
import ShopTitles from 'components/common/shop/ShopTitles'
export default {
name: 'Category',
data() {
return {
titles:['熱賣','特色精品','精選熱菜','熱賣','特色精品','精選熱菜'],
shopScrollTop:[0, 300, 600, 900, 1200, 1500],
current: 0
}
},
components: {
Shop,
ShopTitles
},
mounted() {
},
methods: {
titleClick(index) {
this.$refs.shop.$el.scrollTo({left: 0, top: this.shopScrollTop[index],behavior: 'smooth'})
},
shopOpsitons(saveY) {
// console.log(saveY)
const Max = Number.MAX_VALUE;
this.shopScrollTop.push(Max);
const length = this.shopScrollTop.length;
for( let i = 0; i < length; i++) {
if((this.current !== i)&&(saveY >= this.shopScrollTop[i] && saveY < this.shopScrollTop[i+ 1])) {
this.current = i
this.$refs.titles.currentIndex = this.current
}
}
}
}
}
</script>
<style scoped>
.category {
height: 100vh;
}
.nav-bar {
width: 100%;
border-bottom: 2px solid #333;
height: 160px;
margin: 20px 0;
position: fixed;
z-index: 10;
}