Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the method of dependency injection in the front end of Web

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article introduces the knowledge of "what is the method of dependency injection in the front end of Web". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

What is IoC

The full name of IoC is Inversion of Control, which can be translated as "control inversion" or "dependency inversion". It mainly contains three criteria:

1. High-level modules should not rely on low-level modules, they should all rely on abstraction.

2. Abstraction should not depend on concrete implementation, and concrete implementation should depend on abstraction.

3. Interface-oriented programming rather than implementation-oriented programming

Concepts are always abstract, so here is an example to explain the above concepts:

Suppose you need to build an application called App, which includes a routing module Router and a page monitoring module Track, which may be implemented at first:

/ / app.js

Import Router from'. / modules/Router'

Import Track from'. / modules/Track'

Class App {

Constructor (options) {

This.options = options

This.router = new Router ()

This.track = new Track ()

This.init ()

}

Init () {

Window.addEventListener ('DOMContentLoaded', ()) = > {

This.router.to ('home')

This.track.tracking ()

This.options.onReady ()

});

}

}

/ / index.js

Import App from 'path/to/App'

Ew App ({

OnReady () {

/ / do something here...

}

});

Well, there seems to be no problem, but the requirements in practical applications are very changeable, and you may need to add new features to routing (such as implementing the history pattern) or update the configuration (enable history, ew Router ({mode: 'history'})). This means that the two modules have to be modified within App, which is an operation of INNER BREAKING, and for App that has passed the previous test, it must also be retested.

Obviously, this is not a good application structure. High-level module App depends on two low-level modules Router and Track. Modifications to low-level modules will affect high-level module App. So how to solve this problem? the solution is dependency injection (Dependency Injection) that we will talk about next.

Dependency injection

To put it simply, the so-called dependency injection is to "inject" the dependency into the module by passing parameters. The above code can be modified into the following ways by dependency injection:

/ / app.js

Class App {

Constructor (options) {

This.options = options

This.router = options.router

This.track = options.track

This.init ()

}

Init () {

Window.addEventListener ('DOMContentLoaded', ()) = > {

This.router.to ('home')

This.track.tracking ()

This.options.onReady ()

});

}

}

/ / index.js

Import App from 'path/to/App'

Import Router from'. / modules/Router'

Import Track from'. / modules/Track'

Ew App ({

Router: new Router ()

Track: new Track ()

OnReady () {

/ / do something here...

}

});

As you can see, the INNER BREAKING problem mentioned above is solved by dependency injection, and each module can be modified directly outside the App without affecting the interior.

Will everything be all right? The ideal is very plump, but the reality is very bony. In less than two days, the product gives you a new requirement to add a sharing module Share to App. This goes back to the INNER BREAKING problem mentioned above: you have to modify the App module with a line this.share = options.share, which is obviously not what we expected.

Although App decouples the dependency relationship with several other modules to some extent by dependency injection, it is not thorough enough. The attributes such as this.router and this.track are still dependent on "concrete implementation", which obviously violates the criterion of IoC thought, so how to further abstract the App module.

Talk is cheap, show you the code

Class App {

Static modules = []

Constructor (options) {

This.options = options

This.init ()

}

Init () {

Window.addEventListener ('DOMContentLoaded', ()) = > {

This.initModules ()

This.options.onReady (this)

});

}

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))

}

}

After the transformation, there is no "concrete implementation" in App, and we can no longer see any business code, so how to use App to manage our dependencies:

/ / modules/Router.js

Import Router from 'path/to/Router'

Export default {

Init (app) {

App.router = new Router (app.options.router)

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])

Ew App ({

Router: {

Mode: 'history'

}

Track: {

/ /...

}

OnReady (app) {

/ / app.options...

}

});

You can find that the App module is also very convenient to use. Use the App.use () method to "inject" dependencies, and initialize the relevant configuration in. / modules/some-module.js according to certain "conventions". For example, if you need to add a Share module at this time, you do not need to modify the content inside the App:

/ / 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)

Ew App ({

/ /...

OnReady (app) {

App.setShare ({

Title: 'Hello IoC.'

Description: 'description here...'

/ / some other data here...

});

}

});

Directly outside the App to use the Share module, which is very convenient for module injection and configuration.

So what exactly has been done within App? let's start with the App.use method:

Class App {

Static modules = []

Static use (module) {

Array.isArray (module)? Module.map (item = > App.use (item)): App.modules.push (module)

}

}

It is clear that App.use does a very simple thing, which is to save the dependency in the App.modules property and wait for it to be called when the module is initialized later.

Next let's take a look at what the module initialization method this.initModules () does:

Class App {

InitModules () {

App.modules.map (module = > module.init & & typeof module.init = = 'function' & & module.init (this))

}

}

You can find that this method also does a very simple thing, which is to traverse all the modules in App.modules to determine whether the module contains an init attribute and the attribute must be a function. If the judgment passes, the method executes the module's init method and passes the instance this of App into it, so that it can be referenced in the module.

As you can see from this method, to implement a module that can be App.use (), two "conventions" must be met:

1. The module must contain the init attribute

2. Init must be a function

In fact, this is a good embodiment of the principle of "interface-oriented programming rather than implementation-oriented programming" in IoC. App doesn't care about what the module implements, as long as it satisfies the "convention" of the interface init.

At this point, if you go back to the implementation of Router's module, you can easily understand why and how to write it:

/ / modules/Router.js

Import Router from 'path/to/Router'

Export default {

Init (app) {

App.router = new Router (app.options.router)

App.router.to ('home')

}

}

This is the end of the content of "what is the method of dependency injection in the front end of Web". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report