目錄
一、專案描述
1.1 如何運行
1.2 專案演示?
二、專案頁面及功能
三、專案技術堆疊
四、準備作業
4.1 利用腳手架3創建專案開發環境,并劃分目錄結構;
4.2 css檔案的引入:base.css normalize.css
4.3 專案的模塊劃分:tabbar -> 路由映射關系
4.4 小圖示的修改
4.5 創建vue.config.js檔案,給專案目錄起別名,便于開發
五、功能點代碼梳理
5.0 總體框架
5.1 首頁開發
5.1.1 首頁導航欄的封裝與使用
5.1.2 請求首頁多個資料
5.1.3 Swiper輪播圖組件展示
5.1.4 推薦資訊展示
5.1.5 FeatureView的封裝
5.1.6 首頁商品資料的請求
5.1.8 首頁商品資料的展示
5.1.9 TabControl組件封裝與切換商品
5.1.10 對滾動進行重構- BScroll的封裝和使用
5.1.11 回到頂部- Backtop組件的封裝和使用
5.1.12 BackTop的顯示和隱藏
5.1.13 上拉加載更多
5.1.13 Home離開時記錄狀態和位置
5.2 詳情頁開發
5.2.1 詳情頁資料獲取并展示
5.2.3 頂部標題與頁面內容的聯動效果
5.2.4 底部工具列的封裝
5.2.5 詳情頁回傳頂部
5.2.6 點擊加入購物車
5.2.7 封裝工具函式utils.js進行時間格式化
5.3 購物車頁面
5.3.1 購物車串列展示
5.3.2 購物車標題匯總數量生成
5.3.3 購物車底部封裝和應用
5.3.4 toast插件的封裝與使用
六、專案總結
6.1 Bug解決
6.2 做了那些優化?
6.3 Vuex的應用體現?
6.4 哪些地方用了組件通信?父子和非父子組件間怎么通信?
6.5 專案難點在那幾個地方?
6.6 待完善的點有那些?
一、專案描述
基于Vue全家桶構建的移動端購物商城,頁面共分為:首頁,詳情頁,分類頁,購物車頁面和個人資訊頁
gitee地址:https://gitee.com/mgslsdt/supermall
1.1 如何運行
# 克隆
git clone https://gitee.com/mgslsdt/supermall.git
# 打開專案目錄
cd supermall
# 安裝依賴
npm install
# 開啟本地服務運行專案
npm run serve
1.2 專案演示
二、專案頁面及功能

Home商城首頁:
NavBar利用具名插槽實作三欄布局- 利用
axios進行服務端通訊獲取介面資料Swiper輪播圖組件TabControl控制商品串列展示TabControl標簽吸頂- backTop利用scrollTo回傳頂部
- 封裝第三方庫
better-scroll,處理商品串列滾動- 利用
mixin混入添加防抖函式debounce

商品詳情頁:
- 根據id獲取商品資料保存并展示
- 封裝工具函式
utils.js進行時間格式化- 實作標題和內容的聯動效果,既點擊標題滾動到對應的主題內容(反之亦可)
- 封裝
Toast彈窗插件

購物車頁面:
CheckButton商品全選按鈕
Vuex對購物車進行狀態管理(總計金額與商品相關聯,購物車總數與去計算資料更新 )Vue.js組件復用
三、專案技術堆疊
Vue.js + Vue Router + Vuex + axios
Vue CLI3快速搭建Vue開發環境以及對應的webpack配置;
Vue-router完成頁面的跳轉及部分資料的傳遞;
Vuex完成多個頁面之間的狀態管理
axios請求頁面所需要的資料
四、準備作業
4.1 利用腳手架3創建專案開發環境,并劃分目錄結構;


4.2 css檔案的引入:base.css normalize.css

4.3 專案的模塊劃分:tabbar -> 路由映射關系
<template>
<div id="app">
<keep-alive exclude="Detail">
<router-view></router-view>
</keep-alive>
<main-tab-bar></main-tab-bar>
</div>
</template>
4.4 小圖示的修改


4.5 創建vue.config.js檔案,給專案目錄起別名,便于開發

五、功能點代碼梳理
5.0 總體框架
tabbar+路由組件映射
main-tab-bar=>tab-bar=>tab-bar-item依次呼叫組件



- 路由組件對應

效果

5.1 首頁開發
開發原則:保證首頁邏輯簡單清晰,有必要封裝組件
5.1.1 首頁導航欄的封裝與使用
封裝公共navbar組件,利用具名插槽實作組件復用(home,deatil,cart)
<template>
<div class="nav-bar">
<div class="left"><slot name="left"></slot></div>
<div class="center"><slot name="center"></slot></div>
<div class="right"><slot name="right"></slot></div>
</div>
</template>
<script>
export default {
name: "NavBar"
}
</script>
<style scoped>
.nav-bar {
display: flex;
height: 44px;
line-height: 44px;
text-align: center;
color: #fff;
box-shadow: 0 1px 1px rgba(100,100,100,.1);
}
.left,.right{
width: 60px;
}
.center{
flex: 1;
}
</style>
購物街使用center插槽
效果

5.1.2 請求首頁多個資料
- 安裝axios
- 創建axios實體
- 發送網路請求

- network新建home.js 回傳首頁資料請求

- 拿到資料

- vue結果驗證

5.1.3 Swiper輪播圖組件展示
- 組件輪播圖的實作:
Swiper、SwiperItem - 輪播組件使用
HomeSwiper、DetailSwiper


- home.vue中使用
HomeSwiper組件,初始化banners,并傳入資料banners
![]()
效果

5.1.4 推薦資訊展示
- homeComps下新建檔案 recommendView.vue


展示組件,并傳入從服務端獲取的資料

效果

5.1.5 FeatureView的封裝
- childComps下新建檔案FeatureView.vue檔案
- div>a>img

![]()
效果

5.1.6 首頁商品資料的請求
- 先設計資料結構用于保存資料

- 發送資料請求
- 在home.js中封裝getHomeGoods(type,page)

2. 在home.vue中,又在methods中getHomeGoods(type),通過呼叫this.getHomeGoods('pop')、this.getHomeGoods('new') 、this.getHomeGoods('sell'),
- 動態獲取對應的page
- 獲取到資料:res
-
this.goods[type].list.push(...res.data.list) this.goods[type].page += 1

結果:
goods:{
pop:page1/list[30]
new:page1/list[30]
sell:page1/list[30]
}
5.1.8 首頁商品資料的展示
- 封裝Goodlist.vue組件

- 封裝Goodlistitem.vue組件

5.1.9 TabControl組件封裝與切換商品
- props->titles
- div->根據titles v-for遍歷div->span{{title}}
- css相關
- 選中哪一個tab,哪一個tab文字顏色變色,下面border-bottom
- 借助currentindex

對tab-control組件進行點擊監控,要把所點擊index傳入到父組件home.vue,在home中根據index切換商品型別



5.1.10 對滾動進行重構- BScroll的封裝和使用
原生scroll卡頓,且無法回彈,故使用封裝后的bscroll,絲滑可回彈,content必須要有高度
- 對better-scroll進行封裝:Scroll.vue
- Home.vue和Scroll.vue之間進行通信
- Home.vue將probeType設定為3
- Scroll.vue需要通過$emit,實時將事件發送到home.vue




- 中間content高度計算方法


5.1.11 回到頂部- Backtop組件的封裝和使用

- 如何監聽組件的點擊?直接監聽不可以,必須添加.native修飾符

- 點擊回到頂部 this.$refs.scroll.scrollTo(0,0,500)
5.1.12 BackTop的顯示和隱藏
- isShowBackTop : false
- 監聽滾動,拿到滾動的位置
- 通過v-show決定標識是否被顯示

5.1.13 上拉加載更多
pullUpLoad默認值是false
此處,pullUpLoad并沒有給死,首頁傳遞true,pullUpLoad就是true




5.1.14 tab-control的吸頂效果
思路:必須要知道向上滾動多少時,開始有吸頂效果=>獲取到tabControl的offsetTop
踩坑:組件沒有offsetTop,但所有組件都有一個屬性$el:用于獲取組件中的元素

直接在mounted中獲取tabControl的offsetTop(console.log(this.$refs.tabControl.$el.offsetTop)這里獲取不夠準確,可能圖片還沒有加載完,故等輪播圖加載完再獲取
監聽HomeSwiper中img的加載完成
加載完成后,發出事件,在home.vue中,獲取正確的值
補充:為了不讓HomeSwiper多次發出事件,可以使用isLoad的變數進行狀態的記錄




原本思路是讓tabControl向上移動到一定程度,設定fixed固定定位,
但在動態改變tabControl的樣式時,會出現兩個問題
1.下面商品會突然上移(因為fixed脫標)
2.tabControl雖然設定了fixed但也跟著better-scroll一起上移
故采用在nav-bar底下多復制一份PlaceHolderTabControl組件物件,利用它來實作停留效果,
當用戶滾動到一定位置,PlaceHolderTabControl顯示
當用戶滾動沒有達到一定位置,PlaceHolderTabControl隱藏



這里要注意兩個tabControl點擊index還沒有保持一致

措施:區分兩個ref 在tabClick修改對應的currentIndex


此時,吸頂效果完成

5.1.13 Home離開時記錄狀態和位置
讓Home不要隨意銷毀掉
- 每次離開home,資料都會被銷毀 無法保存


措施:加keep-alive 但再次回傳home頁面 之前瀏覽位置記憶被消除,是bscroll的原因

措施:
- 每次離開home前保留y值,
- 再回到home時讓頁面滾動到之前的y值
- 為防止無法拖動,再次進行重繪


5.2 詳情頁開發
5.2.1 詳情頁資料獲取并展示
- 新建Detail檔案并配置路由關系
- GoodsListItem點擊事件
- 點擊之后獲取商品IID,跳轉詳情頁,并傳入iid
- 根據id請求商品其余資料并展示
- 推薦資料獲取并展示






詳情頁參考各個組件,具體各個組件見代碼
- 在商品基本資訊展示板塊需要注意:當后端傳遞過來海量資料 資料獲取并不統一,而是來自3個不同的物件
- 解決思路:把3個物件資料整合成一個物件資料(創建類-一個物件),傳給組件,讓組件面向這一個物件開發





5.2.2 頂部標題Detailnavbar實作

點擊標題,對應高亮顯示


5.2.3 頂部標題與頁面內容的聯動效果
- 點擊標題,頁面滾動到對應位置


themeTopYs[index] 里面的資料從哪里獲取是個問題
以下是在Deatail----created中

函式呼叫放在圖片加載完成后(等待圖片加載完后,值才是正確的)

但圖片加載后會出現多次回呼,為提高性能,采用防抖


滾動到對應主題:獲取所有主題的offsetTop
問題:哪里才能獲取到正確的offsetTop?
- 1.created肯定不行,壓根不能獲取元素
- 2.mounted也不行,資料還沒有獲取到
- 3.獲取到資料的回呼中也不行,DOM還沒有渲染完
- 4.$nextTick也不行(對應dom已經被渲染,但是圖片依然沒有加載完成),因為圖片的高度沒有被計算在內
最后,在圖片加載完后,獲取的高度才是正確
結果 在圖片加載完后實作一次回呼,同時可實作標題和頁面內容上下聯動

2、內容滾動,顯示正確的標題


5.2.4 底部工具列的封裝


5.2.5 詳情頁回傳頂部
仿照home回傳頂部,同樣的組件復制兩遍,因此可將兩個組件公共代碼進行抽取放在mixin中



公共組件引入detail和home


5.2.6 點擊加入購物車
保存需要存盤到購物車的資料,此處用到vuex進行狀態管理


1.獲取購物車需要展示的商品資訊
????
2.把商品添加到購物車--用到Vuex
利用vuex對狀態進行保管,可以實作購物車相關資料在多個界面進行共享
安裝vuex store中新建index.js




mutation需要進一步判斷


驗證結果:

- mutations唯一目的就是修改state中狀態
- mtations中每個方法盡可能完成事件單一一點
Vuex中,有異步操作和復雜邏輯的建議放在action中修改state,便于后期對mutions直接跟蹤和后期維護,
結果雖然原本簡單的代碼可能會被修改的稍微復雜,但在復雜大專案中優勢比較明顯
- 接下來需要對vuex進行重構
代碼修改
1.把mutation中內容轉移到actions中


2.之前mutation中一個方法判斷兩個情況,現在mutations中內容進行分情況處理(counter++,addtocart),在大專案中便于追蹤

分開前

分開后

當前,是把state,mutations,actions全放在一起,因此還可以進一步重構

actions

mutations

indexs重組后

綜上,重構體現在兩個地方
1.mutation中之前一個操作通過actions分成兩個操作,讓mutation保持每種方法只辦一件事
2.把index.js中state,mutations,actions進行分離,讓代碼看起來更簡潔
5.2.7 封裝工具函式utils.js進行時間格式化

5.3 購物車頁面

5.3.1 購物車串列展示
CartListItem=》CartList=》cart


5.3.2 單選按鈕CheckButton


- 單選按鈕選中狀態判斷

5.3.2 購物車標題匯總數量生成

購物車標題數量來自于vuex中cartlist的長度

當多次呼叫時候,可進行computed計算屬性


進一步,可使用getter.js

同時引入新知識點
mapGetters以及兩種用法,方便了購物車匯總數量的引入

5.3.3 購物車底部封裝和應用

1.全選按鈕的實作:當購物車串列左側全部均選中時候

全選顯示狀態:判斷是否有一個不選中,全選就是不選中

點擊全選按鈕
- 如果原來都是選中,點擊一次,全部不選中
- 如果原來都是不選中(部分選中),全部選中

2. totalPrice計價

3. 去計算 : {{checkLength}}

5.3.4 toast插件的封裝與使用
toast普通封裝
toast插件封裝
采用普通方式封裝有時候存在一些壁壘
采用插件方式封裝,可直接呼叫插件的安裝函式 $toast.show()在頁面顯示即可, 方便多處呼叫,
原理:將toast封裝在插件中 ----安裝插件----組件創建開始就添加到body中---利用插件的安裝函式在頁面顯示
步驟1:自行新建toast組件


步驟2:index.js中新建obj物件
import Toast from "./Toast";
import Vue from "vue";
const obj = {}
export default obj
步驟3:main.js中安裝toast插件
import Vue from 'vue'
import App from './App.vue'
import toast from "components/common/toast" //匯入自己封裝的toast插件
// 安裝toast插件
Vue.use(toast);
new Vue({
render: h => h(App),
router,
store,
}).$mount('#app')
步驟4:index.js中--安裝toast程序中成功添加到Vue原型上
import Toast from "./Toast";
import Vue from "vue";
const obj = {}
obj.install=function(vue){
// 1.創建組件構造器
const toastConstructor = Vue.extend(Toast);
// 2.使用new創建一個組件實體物件
const toast = new toastConstructor();
// 3.將這個實體物件掛載到某個div上
toast.$mount(document.createElement('div'))
// 4.toast.$el對應的就是div
document.body.appendChild(toast.$el)
// 5.將實體添加到Vue的prototype上
Vue.prototype.$toast = toast;
};
export default obj
步驟5:toast插件使用show方法
<template>
<div class="toast" v-show="isShow">
<div >{{message}}</div>
</div>
</template>
<script>
export default {
name: "Toast",
data() {
return {
isShow: false,
message: ''
}
},
methods:{
show(message="默認值",duration = 1500){
this.isShow = true;
this.message = message;
setTimeout(()=>{
this.isShow = false
this.message = " "
},duration)
}
}
}
步驟6:addCart點擊中使用$toast中show方法顯示toast

點擊去計算也可以呼叫toast的show方法
疑惑:
.then來自于action中promise物件,有resolve出兩個不同文案,故,then中res就是他兩,

結果展示:


toast封裝-插件方式的封裝價值和意義在于封裝一次,可以在多處直接使用$toast.show('商品成功添加到購物車',2000)來顯示所需要的toast,
與傳統方式封裝相比,在多次參考組件時候,避免了頻繁的 引入組件-注冊組件-顯示組件-向子組件傳遞引數等多次流程
六、專案總結
6.1 Bug解決
以首頁可滾動區域的bug為例
- 原因分析



- 解決方案---引入事件總線
goodlistitem---this.$bus.$emit('aaa')
home---this.$bus.$on('aaa')




解決滑動區域時頻繁重繪,所以對refresh進行防抖操作
6.2 做了那些優化?
-----性能上優化:
1. 防抖
核心思想:每次事件觸發在延誤時間內,清除定時器,然后重新建立新定時器,直到不再觸發事件為止,

防抖應用1:首頁可滾動區域的refresh:利用better-scroll實作頁面滾動,better-scroll可滾動區域時根據其內容決定,初始內容圖片沒有完全加載,導致可滾動區域不準確(比較短),當圖片完全加載后,則可滾動區域和內容出現矛盾,導致滾動無法繼續,解決方案是監聽每一張圖片是否加載完成,只要有圖片加載完了就執行一次refresh,這樣則執行非常頻繁,因此所以這里對refresh進行防抖操作,將refresh函式傳入到dobounce函式中,生成新的函式,之后在呼叫頻繁的時候就執行新的函式,這個新的函式并不會頻繁的被呼叫,如果下一次請求來的非常快,那么會取消上一次定時器,重新定時,直到在一定時間內沒有新的請求執行refresh函式,

防抖應用2:詳情頁標題和滾動內容的聯動:既點擊標題頁面滾動到對應區域,這時候需要獲取每個組件的offsetTop,并進行push到一個陣列,在滾動時候,會列印出一系列offsetTop陣列,但是每個組件只需要一個offsetTop值,所以在這個地方進行防抖操作

2. 解決移動端300ms的延遲:FastClick的實作原理是在檢測到touchend事件的時候,會通過DOM自定義事件立即發出模擬的click事件,并把瀏覽器在300ms之后的click事件阻止掉,
3. 圖片懶加載:
核心:用到時候再加載
針對某些圖片特別多的頁面,一下子全部加載就會很慢且可能會造成資源浪費,我們將頁面未出現在可視區域內的圖片先不做加載,等到滾動到可視區域在加載,這樣提高頁面加載性能,也提升了用戶體驗,
![]()
-----代碼優化
混入Mixin:相同的組件參考可進行mixin,減少組件的代碼
- 在首頁、詳情頁和分類頁面使用BackTop組件,對其進行了混入
- 因為在首頁、詳情頁和分類頁面都用到了Better-Scroll插件,在鉤子函式mounted中監聽圖片的加載,將此mounted函式進行了混入
6.3 Vuex的應用體現?
Vuex用于多界面狀態管理 商品詳情頁中點擊加入購物車按鈕,先定義一個陣列cartlist用于存放加入購物車商品的資訊,find() 來判斷當前加入陣列的商品是否已經添加到陣列中,之后commit兩個mutations來修改狀態,一個用于修改已經加入陣列中的商品的數目,另一個用于將新商品添加到陣列中, 購物車頁面顯示的商品以及結算的數量和總價格都是由陣列cartlist管理的,




6.4 哪些地方用了組件通信?父子和非父子組件間怎么通信?
父子組件通信
每一個頁面都對應著一個.vue檔案和childComps檔案,比如首頁對應的是home.vue,在這個檔案中通過封裝的axios組件向服務端請求所需要的的資料保存在home.vue中,子組件中需要的資料可以通過props來獲取,當子組件中有事件觸發的時候通過&emit向父組件發出事件,
非父子組件通信:
首頁中商品通過goodslist組件來展示,goodslist組件通過遍歷goodsitem組件得到,所以goodsitem組件和首頁主頁面是非父子的關系,非父子組件通信可通過事件總線來實作,當圖片加載完成時,goodsitem組件中this.$bus.$emit發出事件,home.vue 中this.$bus.$on來監聽事件并進行后續操作,當離開當前頁面,即在deactived中通過this.$bus.$off可以取消對圖片加載的監聽,
6.5 專案難點在那幾個地方?
主要就是代碼的組織、bug處理和復雜業務邏輯問題
- 請求到的資料的保存(尤其是資料來自于不同的物件,需要構建類創建物件來保存)
- 解決可滾動區域的問題(bug原因分析+事件總線引入)
- 標題和內容的聯動效果(offsetTop獲取push到陣列后進行條件判斷)
- 商品添加到購物車(用Vuex建立cartlist保存資料以及商品狀態更改)
6.6 待完善的點有那些?
頁面功能的完善:購物車界面直接實作商品數量增減;分類頁面功能完善
增加和服務端互動:增加登錄注冊
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/296893.html
標籤:其他
上一篇:Axios
下一篇:Vue.js框架基礎

