這個(gè)項(xiàng)目從開始去看項(xiàng)目用到的技術(shù)到結(jié)束林林總總大概花了25個(gè)工作日,跟我之前做的項(xiàng)目相比垛膝,算是比較復(fù)雜的項(xiàng)目了锤灿。 趁著前端沒什么問(wèn)題赘艳,其他技術(shù)在改bug的時(shí)間酌毡,寫下此篇文章來(lái)總結(jié)一下。
項(xiàng)目介紹
24h 導(dǎo)播臺(tái)是一個(gè)類似于官方電視臺(tái)(直播間)的東西第练,電視臺(tái)里播放的內(nèi)容會(huì)按照運(yùn)營(yíng)的設(shè)置而改變阔馋,這個(gè)系統(tǒng)的使用者---運(yùn)營(yíng)就像是電視臺(tái)中的導(dǎo)播。在導(dǎo)播臺(tái)中運(yùn)營(yíng)可以自己編排待播主播娇掏,并且可以設(shè)置他們的上播時(shí)間以及次序呕寝,或者選擇要不要給直播間加個(gè)特效。在YY直播中已經(jīng)有了此功能婴梧,見圖1下梢。在 虎牙里面也有此項(xiàng)功能,但是用的頻次不高塞蹭,之前都是靠運(yùn)營(yíng)同學(xué)手動(dòng)切換某個(gè)直播間的直播流孽江,風(fēng)險(xiǎn)較大且人力成本高(需要蹲守值班),這個(gè)系統(tǒng)就是讓運(yùn)營(yíng)同學(xué)解放雙手的番电。
先大致瀏覽一下這個(gè)系統(tǒng)的全貌岗屏,見圖2辆琅。系統(tǒng)功能大概分為了上播隊(duì)列,預(yù)覽畫面这刷,直播畫面婉烟,輸入畫面,模板設(shè)置和權(quán)限管理等功能暇屋。
項(xiàng)目細(xì)節(jié)
-
技術(shù)選型
從上面的截圖上我們可以了解到似袁,這個(gè)系統(tǒng)中數(shù)據(jù)狀態(tài)很多,很明顯不適合使用jQuery咐刨,適合使用“現(xiàn)代”一些的框架昙衅。加上之前有過(guò)Vue.js的使用經(jīng)驗(yàn)以及后臺(tái)系統(tǒng)沒有對(duì)瀏覽器的兼容要求,就選擇了Vue做為主框架進(jìn)行開發(fā)定鸟,使用了官方的腳手架vue-cli,用了一直想試試但是沒試過(guò)的ES6語(yǔ)法而涉,以及vue官方指定的ajax庫(kù)---axios。
-
項(xiàng)目結(jié)構(gòu)
一圖頂前言仔粥,直接畫了個(gè)圖婴谱。見圖三蟹但∏可能api center 需要解釋一下,api center里面封裝了與接口通信的方法华糖,與組件進(jìn)行了分離麦向,當(dāng)組件需要調(diào)用時(shí)才引入。
-
項(xiàng)目難點(diǎn)分析
回過(guò)頭看客叉,整個(gè)項(xiàng)目的難點(diǎn)主要在以下四個(gè)方面诵竭。
- 邏輯復(fù)雜(例:主要是上播隊(duì)列和輸入畫面這部分,很復(fù)雜,很多邊界情況)
- 數(shù)據(jù)同步(例: 輸入畫面和上播隊(duì)列之間同步狀態(tài)兼搏,以及后臺(tái)接口坑爹卵慰,有很多應(yīng)由后臺(tái)處理的邏輯沒處理)
- 交互復(fù)雜 (例:上播隊(duì)列和輸入畫面的操作)
下面舉幾個(gè)例子,仔細(xì)講講:
實(shí)時(shí)的上播隊(duì)列
功能點(diǎn)分析
- 實(shí)時(shí)的佛呻,會(huì)局部刷新數(shù)據(jù)
- 在頁(yè)面上進(jìn)行操作裳朋,只有“添加主播”和“切下一個(gè)”是直接生效,進(jìn)行其他操作后必須“發(fā)布”才能生效
- 可以對(duì)隊(duì)列進(jìn)行“上移吓著,下移鲤嫡,移除,設(shè)置時(shí)長(zhǎng)”操作绑莺,進(jìn)行操作后暖眼,頁(yè)面上顯示改變,并且上播時(shí)間和開播時(shí)長(zhǎng)均由前端計(jì)算
- 數(shù)據(jù)同步纺裁,由于需求是可以在隊(duì)列中加入相同的主播诫肠,后臺(tái)是把每條記錄當(dāng)成不同的來(lái)處理,所以每個(gè)主播的上播時(shí)長(zhǎng)以及品類和輸入流監(jiān)控是不同的,需要前端做同步邏輯栋豫,以及控制“加入監(jiān)控”的入口惭缰,只讓相同主播中的第一個(gè)主播才會(huì)有“加入監(jiān)控”的按鈕
實(shí)現(xiàn)思路
1 . 維護(hù)兩套數(shù)據(jù),一套是用戶的配置數(shù)據(jù)笼才,另一套是處理過(guò)的接口數(shù)據(jù)漱受,定時(shí)刷新,經(jīng)過(guò)比對(duì)后骡送,選擇局部刷新配置數(shù)據(jù)或者直接替代配置數(shù)據(jù)
2 . 勾選主播后昂羡,進(jìn)行“上移,下移摔踱,移除虐先,設(shè)置時(shí)長(zhǎng)”操作,操作數(shù)組派敷,計(jì)算第一個(gè)主播的時(shí)間蛹批,然后再遍歷計(jì)算其他主播的上播時(shí)間
3 . 比對(duì)配置數(shù)據(jù)和接口數(shù)據(jù),當(dāng)只有‘輸入流監(jiān)控篮愉,直播狀態(tài)腐芍,品類’其中一項(xiàng)或者多項(xiàng)發(fā)生改變時(shí),接口數(shù)據(jù)不會(huì)直接替代配置數(shù)據(jù)试躏,而是會(huì)局部刷新這幾項(xiàng)數(shù)據(jù)
4 . 處理數(shù)據(jù)同步猪勇。 在接口數(shù)據(jù)中,相同主播的‘inputStream’字段的數(shù)據(jù)是不同的颠蕴,我們需要處理泣刹,需要遍歷兩次數(shù)據(jù),然后進(jìn)行替代犀被。并且如果隊(duì)列中有相同的主播且未加入監(jiān)控椅您,則只讓相同主播中的第一個(gè)顯示“加入監(jiān)控入口“。
-
項(xiàng)目?jī)?yōu)化
重構(gòu)和優(yōu)化都是持續(xù)進(jìn)行的寡键,在項(xiàng)目開發(fā)過(guò)程中一直都要進(jìn)行的掀泳,而不是非要等要項(xiàng)目結(jié)束之后再進(jìn)行
- 減少http請(qǐng)求數(shù)
- 頁(yè)面上有很多彈窗,有許多請(qǐng)求會(huì)在彈窗中發(fā)起昌腰】看下面的偽代碼
父組件 A
<template>
<dialog ref='dialog'></dialog/>
</template>
子組件 diaog
<dialog v-if='show'>
</dialog>
dialog.created = ()=>{
// 發(fā)起請(qǐng)求
}
上面代碼的關(guān)鍵點(diǎn)就是當(dāng)組件真正的被渲染之后才會(huì)發(fā)起請(qǐng)求,而不要使用v-show遭商。
- 同樣是上面的例子固灵,頁(yè)面上有彈窗,彈窗顯示后去請(qǐng)求數(shù)據(jù)劫流。但對(duì)于實(shí)時(shí)性要求不高的數(shù)據(jù)巫玻,我們要做處理丛忆,不能每次彈窗顯示就去請(qǐng)求數(shù)據(jù)。偽代碼如下:
dialog組件
<template v-if='show' name='dialog'>
{{data}} // 請(qǐng)求的數(shù)據(jù)
</template>
<script>
export default{
watch:{
show(newVal){
newVal && !data && this.getData();
}
}
}
</script>
上面的思路就是監(jiān)聽show的值仍秤,當(dāng)彈窗顯示后熄诡,先判斷數(shù)據(jù)有沒有存在,沒有的話再去請(qǐng)求诗力。
- 代碼優(yōu)化
代碼優(yōu)化方面比較多凰浮,我重點(diǎn)講下幾個(gè)原則。- 函數(shù)的長(zhǎng)度盡量不要超過(guò)20行,超過(guò)20行之后可讀性會(huì)大大降低
- 單一職責(zé)
- 抽象復(fù)用, 重復(fù)三次以上就有必要抽取出來(lái)
- 函數(shù)的參數(shù)最好不要超過(guò)三個(gè)
-
ES6在項(xiàng)目中的使用
- 模塊化
- 解構(gòu)賦值
解構(gòu)對(duì)象苇本,合并屬性值袜茧,復(fù)制對(duì)象,替代Object.assign - 默認(rèn)參數(shù)
- 箭頭函數(shù)
使用箭頭函數(shù)瓣窄,減少了代碼量笛厦,尤其是使用數(shù)組的一些方法的時(shí)候 - let const
- 數(shù)組,字符串的新方法
find,some,every,includes等方法 - promise 與 async,await(ES7)
- 模板字符串
用來(lái)拼接接口字段和模板
-
async,await 同步的寫法進(jìn)行異步操作
在以往的項(xiàng)目中俺夕,進(jìn)行異步操作的方式大都是寫在回調(diào)函數(shù)里面裳凸,比如說(shuō)是jq的fadeIn,show等函數(shù)以及ajax請(qǐng)求方法,這樣能夠處理異步操作劝贸。但是當(dāng)遇見 A->B->C->D(A,B,C,D函數(shù)均包含了異步操作)這種較為復(fù)雜的情況姨谷,就很容易陷入‘回調(diào)地獄’。除此之外悬荣,如果A菠秒,B疙剑,C氯迂,D為不同模塊的方法,那處理起來(lái)就更煩了言缤,大大的降低了代碼的可讀性嚼蚀。
在新的ES7規(guī)范中,就推出了async,await特性管挟,讓我們用同步的寫法處理異步的操作轿曙。對(duì)于上面的情況,用async,await的寫法如下:
1. async function test(){
await A();
await B();
await C();
await D();
}
2. async function A(){
let res = await getData();
return res.data;
}
async function B(){
let data = await A();
}
異步操作是很容易掉坑里的僻孝,當(dāng)多此進(jìn)行異步操作的時(shí)候导帝,很容易忽略了這個(gè)問(wèn)題,產(chǎn)生了bug.
-
跨組件數(shù)據(jù)共享與數(shù)據(jù)通信
因?yàn)榧夹g(shù)選型的失誤穿铆,加上看了vuex之后一頭霧水您单,沒有使用vue這一數(shù)據(jù)狀態(tài)管理模式,導(dǎo)致后來(lái)在數(shù)據(jù)共享和數(shù)據(jù)同步這方面,寫了很多冗余代碼荞雏。
- 跨組件數(shù)據(jù)共享
還是以系統(tǒng)中的功能為例虐秦。頁(yè)面中有系統(tǒng)配置的功能平酿,每個(gè)人的操作只針對(duì)自己的系統(tǒng)配置。在其他地方可以獲取‘默認(rèn)的上播時(shí)長(zhǎng)’悦陋,通過(guò)sessonStorage來(lái)共享數(shù)據(jù)蜈彼。
當(dāng)需要獲取默認(rèn)上播時(shí)長(zhǎng),先看sessionStorage里有沒有這個(gè)字段,當(dāng)沒有的話再去請(qǐng)求接口數(shù)據(jù)俺驶;
當(dāng)通過(guò)全局設(shè)置進(jìn)行設(shè)置的時(shí)候幸逆,保存之后就會(huì)重新寫入sessionStorage
圖3 設(shè)置時(shí)長(zhǎng)截圖 -
跨組件數(shù)據(jù)通信
跨組件通信的類別主要有父子組件通信,子父組件通信暮现,其他組件間通信秉颗。前兩種就不介紹了,主要是通過(guò)prop 向下傳遞送矩,事件向上傳遞來(lái)通信蚕甥。在本系統(tǒng)中,使用了** event bus ** 作為事件總線
代碼如下:
// eventBus.vue
export default new Vue();
//index.vue
import eventBus from 'eventBus.vue';
eventBus.$on('eventName');
eventBus.$emit('eventName');
通過(guò)eventBus可以傳遞數(shù)據(jù)栋荸,但是有很多問(wèn)題菇怀,在此列舉以下,以后使用此方案的時(shí)候要慎重考慮下:
- 不同組件間相互調(diào)用晌块,可讀性差
- 使用eventBus只能傳遞數(shù)據(jù)爱沟,例如字符串,數(shù)字匆背,對(duì)象等呼伸,但是不能傳遞方法(function)
- 當(dāng)使用eventBus觸發(fā)事件,在事件中進(jìn)行異步請(qǐng)求钝尸,異步請(qǐng)求成功后再告訴事件觸發(fā)的地方括享,只能再去觸發(fā)一個(gè)requestSuceess的事件
經(jīng)驗(yàn)與教訓(xùn)
- 技術(shù)選型要慎重。技術(shù)選型要聽取經(jīng)驗(yàn)豐富的人的意見珍促,項(xiàng)目中沒有使用vuex是很嚴(yán)重的一個(gè)失誤铃辖,在本項(xiàng)目中沒有使用vuex主要是因?yàn)?strong>vuex的學(xué)習(xí)成本稍微有點(diǎn)高,概念不太清楚所以沒使用猪叙。
- 新技術(shù)的學(xué)習(xí)娇斩。 學(xué)習(xí)新技術(shù)能夠開拓視野,提高你技術(shù)的廣度穴翩,提前做好技術(shù)儲(chǔ)備犬第,比等項(xiàng)目來(lái)到手里了再去學(xué)習(xí)要好的多。本項(xiàng)目中對(duì)我來(lái)說(shuō)的新技術(shù)有axios,ES6芒帕。
-
把控好需求再進(jìn)行開發(fā)歉嗓。這個(gè)是這個(gè)項(xiàng)目組沒做好的地方之一。由于項(xiàng)目比較復(fù)雜以及大家都對(duì)導(dǎo)播的這項(xiàng)業(yè)務(wù)不熟悉副签,所以導(dǎo)致后期開發(fā)的時(shí)候很被動(dòng)遥椿。有很多需求是開發(fā)過(guò)程中才明確的基矮,以及開發(fā)過(guò)程中反復(fù)修改,以及新增了很多需求冠场。其中還包括產(chǎn)品沒有和技術(shù)同步需求家浇,前后端都開發(fā)了,但是音視頻那邊沒有開發(fā)功能的需求碴裙。
還有就是第一次的需求評(píng)審會(huì)所有技術(shù)都去了钢悲,唯獨(dú)沒有叫上前端..... - 改善測(cè)試流程。以前做接口比較少的項(xiàng)目沒發(fā)現(xiàn)舔株,做這個(gè)接口很多的項(xiàng)目才感受到前端快成了測(cè)試接口的人了莺琳。必須在界面上進(jìn)行了某項(xiàng)操作之后才能去請(qǐng)求接口,這個(gè)是很多余且繁瑣的操作载慈,很需要改進(jìn)惭等。
- 學(xué)會(huì)拒絕。有很多本應(yīng)該在后端完成的邏輯办铡,但是后端反饋說(shuō)在后端修改比較麻煩辞做,不做。但是基于用戶體驗(yàn)的考慮把這些邏輯在前端處理了寡具,秤茅,,后來(lái)就越來(lái)越麻煩了童叠。
- 新建分支開發(fā)框喳。 做長(zhǎng)期維護(hù)的項(xiàng)目這種技能還是要掌握的