應公司專案需求。 需要在原先完整專案的基礎上將音視訊通話部分與專案進行分離, 形成單獨的元件。 實現在專案中傳入url, 後彈出model框進行兩端音視訊通話。
通話功能
通話功能的流程是通過頁面上的某個按鈕執行init()方法。 因為用了騰訊雲的音視訊技術。 所以需要在騰訊雲伺服器建立房間, 還有公司本地伺服器建立房間做通話兩端的中間人角色。
import rtc from `path`;
rtc.init(
obj, // 建立房間基本資訊欄位
`p1`, // 獲取騰訊雲資訊
`p2`, // 本地伺服器建立房間
`p3`, // 心跳介面
`p4`, // 退出本地伺服器房間
heart, // 心跳回撥 根據返回值檢視視訊過程
eventcb, // 騰訊雲伺服器 發生事件回撥 可不傳
1, // 是否需要混流 可不傳
`p5`, // 混流介面 可不傳
);
在頁面中引入rtc元件並執行init()方法, 傳入路徑,監聽通話過程的回撥等。
在rtc元件中:
const rtc = {
... // 儲存資訊變數
init(obj, u1, u2, u3, u4, heart, eventcb, isMixed = 0, u5 = ``) {
... // 全域性儲存傳入欄位
axios.post(u1, Qs.stringify(params)).then((res) => {
const opt = {
... // 房間資訊
};
const RTC = that.create(opt);
Object.keys(that.events).forEach((key) => {
if (!eventcb) {
that.eventcb = function (rs) {
return rs.tip;
};
} else {
that.eventcb = eventcb;
}
RTC.on(key, that.events[key]);
});
});
}
}
init()方法中通過傳入的路徑, 首先呼叫後臺初始化介面, 獲取建立房間必要的引數資訊。 同時將資訊存入全域性變數中。 執行create()。 開始在伺服器及騰訊雲伺服器建立房間。 在create中 return RTC; 說明房間建立成功。 events 定義了騰訊雲事件通知, 遍歷key, value, RTC.on 進行監聽. eventcb為傳入的事件回撥。
create(opt) {
const self = this;
const RTC = new WebRTCAPI(opt, function () {
const params = {
... // 建立本地伺服器房間
};
axios.post(self.u2, Qs.stringify(params)).then((res) => {
const createOpt = {
... // 建立騰訊伺服器房間
};
RTC.createRoom(createOpt, function() {
console.log(`建立房間`);
self.heartbeat();
})
});
});
return RTC;
},
heartbeat( ) 遞迴呼叫心跳函式, 對通話過程進行監聽, 比如一端退出房間通過與後臺商定的code值, 即使在本地伺服器退出房間等。
events: {
onRemoteStreamUpdate(data) {
... // 遠端流 新增/更新
if (!rtc.connect) {
rtc.connect = 1; // 開始通話
rtc.instance.$emit(`connection`, rtc.connect);
}
rtc.eventcb(....); 回撥返回資訊
},
onRemoteStreamRemove(data) {
... // 遠端流斷開
rtc.eventcb(....);
},
onRelayTimeout(data) {
... // server 超時斷開
rtc.eventcb(....);
}
},
eventcb 如果傳入能確保在執行init( )方法的頁面得到通話過程中的事件執行資訊。
元件通訊
init( )與rtc.js 可以通過回撥傳參的方式進行通訊, 但rtc.js 與 通話皮膚之間無法通過這種方式進行資訊傳遞。 比如需要在rtc.js 通知 model通話開始, 這時需要開始計時等。 vuex, bus無法在這種情況下使用. 所以通過 Vue.extend( ) , 在Vue構造器上建立子類。 註冊到全域性。 使用vm.$emit 及 vm.$om 釋出訂閱事件
import rtcContainer from `./view.rtc`;
init( ... ) {
...
const callPanel = Vue.extend(rtcContainer);
this.instance = new callPanel({
propsData: {
// 傳值
}
}).$mount();
document.body.appendChild(this.instance.$el);
}
如果$mount( )不傳值,沒有掛載節點, 也會生成callpanel例項。這是一個坑,而後將其掛載到body上。 在需要的地方$emit釋出事件.
結語
做完這些初步完成以專案為基礎的元件抽離,程式碼太次,正在優化。