前端中的 IoC 理念
IoC 的全稱叫做 Inversion of Control,可翻譯為為「控制反轉」或「依賴倒置」,它主要包含了三個准則:
1、高層次的模塊(使用依賴的那層)不依賴於低層次的模塊(依賴)。
2、抽象不應該依賴於具體實現,具體實現應該依賴於抽象。(具體實現存在於各模塊)
3、面向接口編程 而不要面向實現編程(下例中,app只管各模塊的init調用)
概念總是抽象的,所以下面將以一個例子來解釋上述的概念:
App.js:沒有「具體實現」,看不到任何業務代碼,只對各模塊進行管理。
class App { static modules = [] constructor(options) { this.options = options; this.init(); } init() { window.addEventListener('DOMContentLoaded', () => { this.initModules(); this.options.onReady(this); }); }
//把依賴保存在了 App.modules 屬性中,后續初始化各注入模塊(initModules)的時候調用各模塊的init(約定模塊要有init) static use(module) { Array.isArray(module) ? module.map(item => App.use(item)) : App.modules.push(module); } initModules() { App.modules.map(module => module.init && typeof module.init == 'function' && module.init(this)); } }
如何使用 App 來管理依賴:通過 App.use() 方法來「注入」依賴,在 ./modules/some-module.js 中按照一定的「約定」去初始化相關配置.
// modules/Router.js import Router from 'path/to/Router'; export default { init(app) { app.router = new Router(app.options.router);//在模塊里去掛載,app里的代碼就不需要具體實現,不會再依賴這個模塊(高層不依賴底層) app.router.to('home'); } }; // modules/Track.js import Track from 'path/to/Track'; export default { init(app) { app.track = new Track(app.options.track); app.track.tracking(); } }; // index.js import App from 'path/to/App'; import Router from './modules/Router'; import Track from './modules/Track'; App.use([Router, Track]); new App({ router: { mode: 'history', }, track: { // ... }, onReady(app) { // app.options ... }, });
比如此時需要新增一個 Share 模塊的話,無需到 App 內部去修改內容,直接在 App 外部去 use 這個 Share 模塊即可,對模塊的注入和配置極為方便。
// modules/Share.js import Share from 'path/to/Share'; export default { init(app) { app.share = new Share(); app.setShare = data => app.share.setShare(data); } }; // index.js App.use(Share); new App({ // ... onReady(app) { app.setShare({ title: 'Hello IoC.', description: 'description here...', // some other data here... }); } });
App 模塊此時應該稱之為「容器」比較合適了,跟業務已經沒有任何關系了,它僅僅只是提供了一些方法來輔助管理注入的依賴和控制模塊如何執行。
控制反轉(Inversion of Control)是一種「思想」,依賴注入(Dependency Injection)則是這一思想的一種具體「實現方式」,而這里的 App 則是輔助依賴管理的一個「容器」。
具體進化過程,看原文:前端中的 IoC 理念