項目倉庫地址:https://github.com/konglingwen94/vue-elm-sell
項目線上地址: http://123.56.124.33:5000
前提
自從學習了Vue
后蜕劝,能用Vue
解決的場景用例最終我都盡可能的用Vue
去實現(xiàn)笆环。單純的用例需求并沒有完整的項目開發(fā)流程级及,從中能學到的東西也是有限的壤躲。在這之前除了使用Vue
做過vue-music的移動端音樂播放器項目和vue-bytedanceJob(重構某獨角獸互聯(lián)網(wǎng)公司官方招聘網(wǎng)站)之外乾蓬,自己并沒有用Vue
涉獵web
端更復雜的業(yè)務場景。
為了找一個項目練習内舟,我去github
上開始了搜索游桩,當看到https://github.com/ustbhuangyi/vue-sell
這個項目時,感覺這個移動端應用的一些業(yè)務場景是自己沒有接觸過的股缸,于是我就照著這個應用的UI
和功能
用自己的知識體系和技術棧進行了重構衡楞,大概不到半個月的時間,我完成了第一個commit
提交到項目上線運行敦姻,本篇文章就從應用功能和技術實現(xiàn)一些方面剖析此項目的開發(fā)過程以及采到的坑瘾境。
項目截圖
<img src="https://user-gold-cdn.xitu.io/2020/7/1/17308b5c66a54ae5?w=286&h=500&f=gif&s=1854225" width="200">
<img src="https://user-gold-cdn.xitu.io/2020/7/1/17308b647f0cba7f?w=286&h=500&f=gif&s=838667" width="200">
<img src="https://user-gold-cdn.xitu.io/2020/7/1/17308b6220974f7e?w=286&h=500&f=gif&s=1786516" width="200">
<img src="https://user-gold-cdn.xitu.io/2020/7/1/17308b316156fd95?w=286&h=500&f=gif&s=954705" width="200">
<img src="https://user-gold-cdn.xitu.io/2020/7/1/17308b33d9cb205e?w=286&h=500&f=gif&s=1187009" width="200">
項目技術棧
-
前端
-
vue
開發(fā)項目核心框架 -
axios
HTTP請求模塊 -
lib-flexible
移動端屏幕適配方案 -
better-scroll
仿IOS
效果的移動端滾動庫 -
normalize.css
第三方css
樣式初始化模塊 -
es 6/7
下一代javascript
語法
-
-
后端
-
express
搭建服務端應用核心框架
-
-
開發(fā)
-
vue-cli
項目初始化腳手架 -
vue-devtools
項目開發(fā)環(huán)境調試工具 -
vscode
chrome
git
macbookpro
-
-
部署
應用功能
-
商品頁
- 商品分類導航和商品列表的聯(lián)動效果
- 點擊商品分類菜單展示對應商品列表信息
- 添加/刪除商品到購物車
- 點擊商品進入到詳情頁面
- 商品添加到購物車動畫效果
- 頁面滾動到對應商品類別時的標題吸頂效果
-
評論頁
- 綜合評論信息渲染
- 切換評論篩選項按鈕展示對應的信息
- 選擇展示
是否有內容的評論
-
商家頁
- 商家店鋪信息展示
- 收藏店鋪
- 商家實景圖片具有
bounce
效果的滑動顯示
-
應用頭部
- 點擊展示詳情
- 公告信息動態(tài)滾動顯示
-
購物車
- 根據(jù)商品個數(shù)顯示不同的狀態(tài)
- 購物車商品列表
- 支付彈窗
- 清空購物車
- 增加/刪除商品
應用局部優(yōu)化
bounce效果
是指在應用中頁面位置滾動到一個端點繼續(xù)滑動時出現(xiàn)反彈的效果,常見場景是IOS
系統(tǒng)應用滑動效果
功能難點
商品導航和內容的左右聯(lián)動效果
效果演示
完整的組件代碼點https://github.com/konglingwen94/vue-elm-sell/blob/master/src/views/goods/index.vue。
思路
由于商品導航和內容是兩個獨立的滾動容器镰惦,當滾動到一個目標內容塊時怎么才能激活它所關聯(lián)的導航項呢?我們知道導航項列表和內容列表在排列順序上是一致的迷守,如果能計算出內容滾動位置處在對應區(qū)間塊的索引,也就得到了導航列表應該激活的目標索引旺入,然后就可以用Vue
數(shù)據(jù)驅動視圖的思想去實現(xiàn)這一切兑凿。
容器的左右聯(lián)動效果是指容器滾動到目標內容時激活其關聯(lián)的導航菜單項并滾動到可視區(qū)域。
邏輯實現(xiàn)
找到要激活的目標導航項索引的第一步需要把商品內容的各個類別塊在容器內的縱坐標位置存儲起來(給之后找到激活的目標索引提供比較對象)茵瘾,由于列表內容時動態(tài)渲染的礼华,所以這里需要等所有數(shù)據(jù)已經(jīng)渲染完成后才能操作,下面直接看代碼演示吧龄捡!
template
部分
<template>
/* 這里只顯示部分代碼*/
<ul class="foods-list">
<li ref="foodsGroup" class="foods-group" v-for="(item,index) in data" :key="index">
<dl class="foods-group-wrapper">
<dt :class="{fixed:currentIndex===index}" class="foods-group-name">{{item.name}}</dt>
<dd
class="foods-group-item"
v-for="(food ,key) in item.foods"
:key="key"
>
{{food.name}}
</dd>
</dl>
</li>
</ul>
</template>
script
部分
export default {
data(){
return {
currentIndex: 0,//導航項激活的索引
currentFood: {},
data:[],
sectionHeight: [0],//第一個高度塊坐標`y`值為`0`
// 渲染完成后的值為 `[0,1281,1459,1612,2000,2270,2565,2952,3574,4436]`
}
},
created() {
request
.get("/goods")
.then(response => {
this.data = response;
})
.then(() => {
setTimeout(() => {
const sections = this.$refs.foodsGroup;
sections.reduce((prevTotal, current) => {
const sectionHeight = prevTotal + current.clientHeight;
this.sectionHeight.push(sectionHeight);
return sectionHeight;
}, 0);
});
});
}
}
有了各個商品塊的y
坐標卓嫂,下一步就需要注冊容器元素的滾動事件了,在回調函數(shù)里通過找到實時滾動位置disanceY
處在sectionHeight
數(shù)組中兩個相鄰元素之間的位置從而就得到了待激活導航索引currentIndex
的值聘殖,具體代碼實現(xiàn)如下
<template>
<div>
<!--導航菜單-->
<scroll class="menu">
<ul class="menu-list">
<li
@tap="selectMenu(index)"
class="menu-item"
:class="{selected:currentIndex===index}"
v-for="(item,index) in data"
:key="index"
>
<span>{{ item.name}}</span>
</li>
</ul>
</scroll>
<!--商品內容-->
<scroll ref="foodsScroll" @scroll="onFoodScroll" class="foods">
<!--這里省略商品內容模板的代碼-->
</scroll>
</div>
</template>
export default {
// 這里省略其他代碼
methods:{
onFoodScroll({ x, y }) {
const distanceY = Math.abs(Math.round(y));
for (let index = 0; index < this.sectionHeight.length; index++) {
if (
distanceY >= this.sectionHeight[index] &&
distanceY < this.sectionHeight[index + 1]
) {
this.currentIndex = index;
}
}
}
}
}
完整的組件代碼點https://github.com/konglingwen94/vue-elm-sell/blob/master/src/views/goods/index.vue晨雳。由于左右兩側的布局容器都是基于
better-scroll
實現(xiàn)的頁面滾動行瑞,所以這里需要偵聽better-scroll
提供的scroll
事件而不是瀏覽器原生的滾動事件。查看better-scroll
的scroll
事件API
點這里餐禁。
添加/刪除 商品到購物車
效果截圖
完整代碼https://github.com/konglingwen94/vue-elm-sell/blob/master/src/components/food-picker/index.vue
思路
添加商品到購物車是一個多場景的功能血久,由于這里的購物車功能是一個多頁面聯(lián)動的效果,購物車商品數(shù)量的實時更改也需要同步到商品內容頁和商品詳情頁帮非。從功能映射到javascript
語言數(shù)據(jù)結構層面的話氧吐,不難想到對象引用傳遞的特點可以作為實現(xiàn)此功能的底層架構思路,那就讓我們去實現(xiàn)它吧末盔。
實現(xiàn)
為了統(tǒng)計商品的數(shù)量筑舅。首先需要給每一個商品信息對象添加一個默認值為0
的count
屬性,添加后的對象長這樣
{
"count": 0, // 此變量用來存儲添加到購物車的數(shù)量
"name": "皮蛋瘦肉粥",
"price": 10,
"oldPrice": "",
"description": "咸粥",
"sellCount": 229,
"rating": 100,
"info": "一碗皮蛋瘦肉粥陨舱,總是我到粥店時的不二之選翠拣。香濃軟滑,飽腹暖心游盲,皮蛋的Q彈與瘦肉的滑嫩伴著粥香溢于滿口误墓,讓人喝這樣的一碗粥也覺得心滿意足",
"ratings": [
{
"username": "3******b",
"rateTime": 1469261964000,
"rateType": 1,
"text": "",
"avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png"
}
],
"icon": "http://fuss10.elemecdn.com/c/cd/c12745ed8a5171e13b427dbc39401jpeg.jpeg?imageView2/1/w/114/h/114",
"image": "http://fuss10.elemecdn.com/c/cd/c12745ed8a5171e13b427dbc39401jpeg.jpeg?imageView2/1/w/750/h/750"
}
由于每一個商品項都有一個添加到購物車的數(shù)量選擇器功能,這樣我們直接給商品數(shù)量選擇器組件設計一個名為foodInfo
的對象類型props
益缎,這樣在增加/減少商品數(shù)量的時候直接操作foodInfo
的count
屬性來實現(xiàn)同步數(shù)據(jù)的效果谜慌。
/components/food-picker.vue 組件代碼
<template>
<div class="food-picker" @click.stop>
<div class="reduce-wrapper" @click="reduce">
<i class="iconfont reduce"></i>
</div>
<div class="counter">{{foodInfo.count}}</div>
<div class="add-wrapper" @click="add">
<i class="iconfont add"></i>
</div>
</div>
</template>
<script>
export default {
name: "food-picker",
props: {
foodInfo: {
type: Object,
default: () => ({})
}
},
methods: {
reduce() {
if (parseInt(this.foodInfo.count) > 0) {
this.foodInfo.count--;
}
},
add() {
this.foodInfo.count++;
}
}
};
</script>
<style lang="less" scoped>
.food-picker {
min-width: 180px;
max-width: 200px;
display: flex;
align-items: center;
width: 100%;
justify-content: space-between;
.iconfont {
color: #00a0dc;
font-size: 38px;
}
.counter {
// margin: 0 20px;
}
}
</style>
下一個目標
基于目前已經(jīng)實現(xiàn)的功能,整個應用的數(shù)據(jù)都是以json
文件的格式存儲在服務器莺奔,服務端并沒有可以用來增刪改查的API
接口可供使用欣范。下一步我計劃做出管理后臺和服務端API
用來管理前端頁面的數(shù)據(jù),使所有模塊的數(shù)據(jù)都是可配置的弊仪,這樣前端所渲染出來的數(shù)據(jù)也都是動態(tài)的,能夠整合三端到一個項目也滿足了當下Web
全棧開發(fā)的場景需要熙卡。
總結
通過真實的開發(fā)這樣一個復雜交互的應用,自己對Vue
在實際業(yè)務場景中的使用和理解有深入了一步励饵。深入理解了Vue
的數(shù)據(jù)驅動視圖改變的思想驳癌,熟練的掌握了組件化開發(fā)項目的流程,同時也感受到所帶來的便利役听,為自己接下來預備做的中大型項目建筑好了橋梁颓鲜。
支持
如果本項目對您學習有幫助,請您動手點個star
https://github.com/konglingwen94/vue-elm-sell典予。也希望您繼續(xù)關注我的動態(tài)https://github.com/konglingwen94甜滨,有了您的支持我會有動力開源更多有趣的項目。
歡迎點贊和留言瘤袖,謝謝衣摩!
本篇文章屬于作者原創(chuàng),轉載參考請注明出處捂敌,謝謝艾扮!