摘要:此文已由作者張磊授權(quán)網(wǎng)易云社區(qū)發(fā)布。歡迎訪問網(wǎng)易云社區(qū),了解更多網(wǎng)易技術(shù)產(chǎn)品運營經(jīng)驗。前言在對蜂巢項目從遷移到的過程中,遇到的問題,以及在此過程中所使用的解決方案。三個頭是一致的。文章來源網(wǎng)易云社區(qū)
此文已由作者張磊授權(quán)網(wǎng)易云社區(qū)發(fā)布。
歡迎訪問網(wǎng)易云社區(qū),了解更多網(wǎng)易技術(shù)產(chǎn)品運營經(jīng)驗。
前言
在對蜂巢項目從 nej + regularjs 遷移到 vue 的過程中,遇到的問題,以及在此過程中所使用的解決方案。
遇到的問題
父子頁面通信
項目分為待重構(gòu)的模塊和已重構(gòu)的模塊,待重構(gòu)的模塊是使用 nej 和 regular ,重構(gòu)的模塊是 vue。頁面是通過 iframe 引用重構(gòu)的模塊。
這里會涉及到幾個問題。iframe 和父窗口數(shù)據(jù)交換問題、模態(tài)框、以及路由同步的問題。 這三個問題的解決方案都是使用了一個通信機(jī)制。這個通信機(jī)制對數(shù)據(jù)進(jìn)行了序列化(在 ie 下,不序列化會遇到暗坑),所以函數(shù)是無法進(jìn)行傳遞的,只可以傳遞值,然后通過 JSON.stringify 序列化成字符串,傳遞過去后再反序列化成相應(yīng)類型。采用這種形式,在項目后期,對代碼進(jìn)行批量修改的時候查找也很方便,甚至可以將通信機(jī)制二次改造,而不需要改業(yè)務(wù)代碼。
問題需要特殊說明的有:
模態(tài)框
由于 iframe 并不是鋪滿整個頁面,在 iframe 內(nèi)部實現(xiàn)模態(tài)框的時候,導(dǎo)致導(dǎo)航欄不會被覆蓋掉。于是就可以看到頁面的一部分變灰,但導(dǎo)航欄還是可以點擊的。同時模態(tài)框的居中是相對于 iframe 的,所以看起來也不是特別居中。暫時解決方案,是使用通信機(jī)制傳參調(diào)用父頁面的模態(tài)框的邏輯。2. 路由同步
nej 和 vue 都有一套路由方案,但是路由的格式是不一致的,同時模塊的命名方案也會不一致,再者 iframe 和 父頁面路由的變更都需要通知到對方。
接下來講通信機(jī)制如何解決問題的。
API
/**
* 發(fā)送信息 * @param {string} receiver 收件人 * @param {string} action 描述 * @param {*} [msg] 內(nèi)容 * @param {function} [cb] 回執(zhí)函數(shù) * @param {boolean} [isTemp] 如果收件人不存在,通過設(shè)置這個參數(shù)來指定該消息是丟棄還是保存,當(dāng)未來某時刻收件人存在的時候,會依次讀取保存的信息,一般不需要指定。 */
send(receiver, action, msg, cb, isTemp) {
},
// Bridge.send("parent", "urlchange", "/module/list");
// Bridge.send("parent", "error", "網(wǎng)絡(luò)出錯");
action 可以在父子頁面的 handles 對象里注冊。eg:
// 父頁面const handles = {
show() { toggle(true); }, hide() { toggle(false); }, hideModal: _u._$hideModal, alert(options) { _u._$alert(options); }, error(msg) { CloudUI.Toast.error(msg); }, confirm(options, cb) { _u._$confirm(Object.assign({ onok() { cb("sub", { msg: true, }); }, oncancel() { cb("sub", { msg: false, }); }, }, options)); },
}
// 子頁面handles.urlchange = function urlchange(path) {
router.replace(path);
};
再來一些復(fù)雜的例子
同步調(diào)用
子頁面向父頁面?zhèn)鬟f數(shù)據(jù)
Bridge.send("parent", "urlchange", "/module/list");// 這里注意一點,為了以后方便,在 vue 模塊內(nèi)部使用的路由均是 vue 的,vue 路由向 nej 路由的轉(zhuǎn)換在 /src/html/module/vue/map.js 進(jìn)行配置,配置信息如下:// {// "/m/module/": "/module/list",// }
父頁面向子頁面?zhèn)鬟f數(shù)據(jù)
Bridge.send("sub", "urlchange", "/module/list");// 而在 nej 模塊,寫路由就可以隨意點,可以直接寫 vue 的路由,也可以讓其進(jìn)行轉(zhuǎn)換,nej 的模塊在后面均會丟棄,所以允許隨意一點
異步調(diào)用
// send(receiver, action, msg, cb, isTemp)Bridge.send("parent", "confirm", { content: "所選快照正在維護(hù)中,創(chuàng)建可能需要等待較長時間,建議稍后再試。", okButton: "繼續(xù)創(chuàng)建", cancelButton: "稍后再試", primaryButton: "cancelButton",
}, (err, status) => { if (status) { this.create();
} else { this.submitting = false; }
});// 其中第四個參數(shù)是回調(diào)函數(shù) callback,模仿 nodejs 的實現(xiàn),err 存在的時候就是失敗,第二個參數(shù)是調(diào)用返回的 message??梢詤⒁娚厦?handles.confirm。
路由
vue 以及 vue-router 支持的異步加載僅僅是組件級別的,而不是路由級別的,所以實現(xiàn)路由級別的異步加載就會繞一些。eg:
// 一般實現(xiàn)const Create = () => import("./create.vue");const List = () => import("./list.vue");
這種方案下,webpack 會對每一個路由進(jìn)行打包,導(dǎo)致一個路由一個 chunk 的模式,前端加載負(fù)擔(dān)過大。實際上,我們需要的粒度可能沒有這么細(xì),在這里使用一種 vue-router 官方的方案(滑到頁面底部)。
// 優(yōu)化實現(xiàn)const Create = () => import(/ webpackChunkName: "a" / "./create.vue");const List = () => import(/ webpackChunkName: "a" / "./list.vue");
這里是使用注釋 / webpackChunkName: "a" / 來標(biāo)明打入同一個 chunk a 中。唯一的坑點是使用注釋。當(dāng)然還有一種方案進(jìn)行處理。eg:
// index.jsexport { default as create } from "./create.vue";export { default as list } from "./list.vue";// route.jsconst Create = () => import("./index.js").then((modules) => modules.create);
路由寫在每個模塊的下面,只存在一個文件。
eg:
// 建議- modules
- moduleA - routes.js
不建議在子目錄放置路由,不清晰,完整的路由,可能需要打開多個文件,才能看到
// 不建議- modules
- moduleA - detail - routes.js - routes.js
建議方案會產(chǎn)生 routes.js 文件變的很龐大的問題,不方便查看??蓞⒖既缦聦懛ǎ梢跃徑獯藛栴}:
const routesA = [];const routesB = [];export default [
...routesA, ...routesB,
]
路由的劃分問題
eg:
// 不建議const router = [
{ path: "/", component: () => import(/* webpackChunkName: "module" */ "./list.vue"), children: [ { path: "tab1", name: "module.list.tab1", // ... }, { path: "tab2", name: "module.list.tab2", // ... }, { path: "tab3", name: "module.list.tab3", // ... }, ], }, { path: "tab1/edit", name: "module.edit.tab1", // ... }
];
module 模塊頁,有三個 tab。三個 tab 頭是一致的。 list.vue 的代碼僅僅是實現(xiàn)了 3個 tab 一致的部分即頭部。觀察 tab1/edit 和 tab1,在邏輯層面上它們應(yīng)該被放到一起,但是 path: "/" 所在的組件的 dom 中含有 3個 tab 的頭,導(dǎo)致沒有辦法寫在一起(寫在一起的話同時會繼承頭部),權(quán)限控制更顯麻煩。更好的做法是 path: "/" 這一層級不做任何 dom 相關(guān)的東西,寫到每個 tab 內(nèi)部。
// 建議const tab1 = { path: "tab1", // 權(quán)限控制 tab1 的準(zhǔn)入 children: [
{ path: "list", name: "module.tab1.list", // ... }, { path: "edit", name: "module.tab1.edit", // ... }, ],
};
const router = [
{ path: "/", // 權(quán)限控制 module 的準(zhǔn)入 children: [ tab1, { path: "tab2", name: "module.tab1.list", // ... }, { path: "tab3", name: "module.tab3.list", // ... }, ], }
];
當(dāng)然可以根據(jù)權(quán)限控制進(jìn)行調(diào)整,寫法不是很固定。交互可能不太喜歡定義 path: "list", 但是第一種寫法,相當(dāng)于污染了整個路由的頂層,那后面必須定義多個頂層進(jìn)行覆蓋,由模塊單入口路由變成了模塊多入口路由。
openapi 和 webapi 數(shù)據(jù)轉(zhuǎn)換
舉例說明:在模塊從 webapi 遷移到 openapi 的時候使用了一種方案,在數(shù)據(jù)獲取層面對數(shù)據(jù)進(jìn)行轉(zhuǎn)換。即:
// openapiconst result1 = { Id: 1, Name: 2,
};// webapiconst result2 = { id: 1, name: 2,
};// transform(result1) 后的數(shù)據(jù)結(jié)構(gòu)包含 result2 中有用的數(shù)據(jù)結(jié)構(gòu)// 這個 transform 函數(shù)會將 openapi 的數(shù)據(jù)轉(zhuǎn)換成 webapi 的,這樣只需要改數(shù)據(jù)結(jié)構(gòu),讓新老保持一致,再修改少量的業(yè)務(wù)邏輯即可完成接口遷移工作。
這個問題本身屬于后端接口變更,與框架遷移屬于并行任務(wù),多帶帶拿來看并無關(guān)聯(lián),問題放在一起的時候,就變得棘手了。
在對 win 模塊進(jìn)行遷移的時候,在使用 vue 的時候希望接口方面使用 opeanpi 的數(shù)據(jù),不進(jìn)行數(shù)據(jù)轉(zhuǎn)換。但是在使用老模塊的時候,為了盡量少的動業(yè)務(wù)代碼,對 opeanpi 的數(shù)據(jù)進(jìn)行了轉(zhuǎn)換,那就意味著兩者的數(shù)據(jù)的并不一致,在使用上面提到的通信機(jī)制(調(diào)用父頁面的模態(tài)框,需要傳遞數(shù)據(jù))的時候,這就很致命了,意味著一方需要再做一次數(shù)據(jù)轉(zhuǎn)換。目前代碼是 vue 模塊手工硬編碼轉(zhuǎn)換的,后面可以把這部分放到 nej ,可以借用其已有的接口的數(shù)據(jù)轉(zhuǎn)換函數(shù),對 vue 傳遞的數(shù)據(jù)進(jìn)行二次轉(zhuǎn)換。
另外還有一個問題,如果模塊先進(jìn)行框架遷移,后進(jìn)行接口遷移,此時就面臨兩個方案。一個是使用 transform 函數(shù)對數(shù)據(jù)進(jìn)行轉(zhuǎn)換,另一種,推到重寫。此時肯定更傾向于第一種方案,那么就需要對 transform 函數(shù)進(jìn)行設(shè)計,讓其更方便使用。這里簡單設(shè)計了一種。
const source = { standard: { bandwidth: 1, ipChargeType: 2
}, instanceId: 6,
};
const rules = { standard: "NewStandard", instanceId: "InstanceId", "standard.bandwidth": ["InternetMaxBandwidth", "BizParam.InternetMaxBandwidth"], "standard.ipChargeType": "BizParam.NetworkChargeType",
};
const out = { NewStandard: { bandwidth: 1, ipChargeType: 2
}, InstanceId: 6, BizParam: { InternetMaxBandwidth: 1, NetworkChargeType: 2, }, InternetMaxBandwidth: 1,
};
it(transform(source, rules) is correct, () => { assert.deepEqual(transform(source, rules), Object.assign({}, source, out));
});
it(transform(source, rules, true) is correct, () => { assert.deepEqual(transform(out, rules, true), Object.assign({}, out, source));
});
靜態(tài)資源
這里主要是 js 文件內(nèi)引用的靜態(tài)資源,該靜態(tài)資源的路徑需要用此語法進(jìn)行設(shè)置
default: { logo: require(@/assets/images/logos/logo.png), // @是項目根路徑},
這樣這個靜態(tài)文件就可以享受到 webpack 的處理,算出正確的路徑,不然有可能出現(xiàn)顯示不出來的情況。 另外靜態(tài)資源不推薦寫相對路徑。eg: ../../../assets/images/logos/logo.png
接口
nej + regular 在代碼里寫了接口,在 vue 需要再次找到接口,重新寫一遍,基本不可復(fù)用。但如果之前放置接口的地方稍顯混亂,那么在找接口的時候,就需要一個個業(yè)務(wù)邏輯的看過去。試想可不可以
將接口按照模塊放置在一起,稱為 api 層,同時再劃分出來 service 層。api 層通過 json 來描述一個接口的方方面面, service 層是從 api 層生成出來的,外加上對接口進(jìn)行二次處理和對多個接口拼接。
然后就很好的抽象出一個獨立的 api 層,和業(yè)務(wù)邏輯無關(guān),僅和后端文檔輸出有關(guān),同時 service 層又很好的保持一定的業(yè)務(wù)相關(guān)性。那么在換框架的時候,api 直接拿走即可,service 層僅需要稍許改動。另有文章介紹具體的實現(xiàn)。
這里可能會有接口數(shù)據(jù)緩存以及一定時間內(nèi)只發(fā)一次請求的需求,那么想一下,需要在該層實現(xiàn)嗎?還是需要更高的一層對數(shù)據(jù)處理的抽象,而不受限于僅對接口數(shù)據(jù)?又或者對 service 層的定義進(jìn)行擴(kuò)充,包含對數(shù)據(jù)處理的抽象?
網(wǎng)易云計算基礎(chǔ)服務(wù)深度整合了 IaaS、PaaS 及容器技術(shù),提供彈性計算、DevOps 工具鏈及微服務(wù)基礎(chǔ)設(shè)施等服務(wù),幫助企業(yè)解決 IT、架構(gòu)及運維等問題,使企業(yè)更聚焦于業(yè)務(wù),是新一代的云計算平臺,點擊可免費試用。
文章來源: 網(wǎng)易云社區(qū)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/25269.html
摘要:本文將介紹網(wǎng)易云基礎(chǔ)服務(wù)蜂巢實例遷移功能的實現(xiàn),并探討如何高效完成實例遷移任務(wù)。網(wǎng)易云基礎(chǔ)服務(wù)蜂巢提供了負(fù)載監(jiān)控閾值選項,在業(yè)務(wù)負(fù)載超過該閾值時,會暫停遷移操作,直到負(fù)載重新低于閾值。 歡迎訪問網(wǎng)易云社區(qū),了解更多網(wǎng)易技術(shù)產(chǎn)品運營經(jīng)驗。 我們把數(shù)據(jù)庫里部分或全部 Schema和數(shù)據(jù)遷移到另一個實例的行為稱為實例遷移,將導(dǎo)出數(shù)據(jù)的實例稱為源實例,導(dǎo)入數(shù)據(jù)的實例稱為目標(biāo)實例。 根據(jù)遷移數(shù)...
摘要:最后,張曉龍透露未來網(wǎng)易云會在以下三個方面繼續(xù)深耕研發(fā)高性能容器,跟進(jìn)開源社區(qū)最新版本并適配,加大參與社區(qū)力度并反饋社區(qū)。文章來源網(wǎng)易云社區(qū) 歡迎訪問網(wǎng)易云社區(qū),了解更多網(wǎng)易技術(shù)產(chǎn)品運營經(jīng)驗。 10 月 15 日,聚焦 Kubernetes 中國行業(yè)應(yīng)用與技術(shù)落地的首屆中國 Kubernetes 用戶大會(KEUC)在杭州成功舉辦。本次大會吸引了來自全球各地的技術(shù)精英齊聚一堂,共同探...
摘要:作為為應(yīng)用平臺即時通訊技術(shù)開發(fā)和部署提供便捷途徑的云平臺,網(wǎng)易云聚焦穩(wěn)定性和易用性,通過強(qiáng)化私有云定制化的服務(wù)來滿足不同用戶的需求,而這正是網(wǎng)易云作為即時通訊領(lǐng)域的老兵的競爭優(yōu)勢所在。9月22日,2017中國移動互聯(lián)網(wǎng)大會暨中國首席技術(shù)官大會在杭州舉行。眾多業(yè)界技術(shù)領(lǐng)袖參與了此次盛會,就互聯(lián)網(wǎng)時代的IT技術(shù)研發(fā)挑戰(zhàn)和應(yīng)對策略進(jìn)行了探討。網(wǎng)易技術(shù)委員會資深專家委員徐杭生在會議上發(fā)表演講,認(rèn)為移...
摘要:在互聯(lián)網(wǎng)的第三個時代,也就是下一個互聯(lián)網(wǎng)十年里,云計算將成為這場大戰(zhàn)的制勝關(guān)鍵所在。就在前不久,亞馬遜旗下的云計算服務(wù)平臺宣布正式在中國商用。的殺入對于中國的云計算市場也是一大不可忽視的力量?! 』ヂ?lián)網(wǎng)的第一個時代我們定義為PC互聯(lián)網(wǎng),互聯(lián)網(wǎng)的第二個時代我們定義為移動互聯(lián)網(wǎng),而互聯(lián)網(wǎng)的第三個時代我們則定義為萬物聯(lián)網(wǎng)。當(dāng)前國內(nèi)的互聯(lián)網(wǎng)正處于第二個時代向第三個時代過渡期,而云計算則是支撐起萬物聯(lián)...
摘要:網(wǎng)易云信即時通訊云服務(wù)的產(chǎn)品優(yōu)勢網(wǎng)易云信涉足多元行業(yè)提升用戶體驗滿足內(nèi)外協(xié)同今年月,網(wǎng)易云信正式宣布通信與視頻業(yè)務(wù)實現(xiàn)戰(zhàn)略升級?! №n寒導(dǎo)演的影片《乘風(fēng)破浪》中,有這樣一個片段,在六一還堅持囤BB機(jī)有前途的時候,從事電腦編程和軟件開發(fā)的小馬則認(rèn)為即時通訊才是未來的發(fā)展方向??吹竭@里,很多觀影者都不謀而合地笑了,小馬口中的即時通訊就是在1999年誕生的OICQ。影片中阿浪說的那句話沒錯,這個世...
閱讀 1850·2021-11-15 11:37
閱讀 3194·2021-11-04 16:05
閱讀 1986·2021-10-27 14:18
閱讀 2808·2021-08-12 13:30
閱讀 2541·2019-08-29 14:18
閱讀 2153·2019-08-29 13:07
閱讀 2102·2019-08-27 10:54
閱讀 2782·2019-08-26 12:15