模块依赖和业务解耦代码实现
前端中的 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 理念