在可测试js的框架学习过程中,我们不断提到了依赖注入,依赖注入使用最多的就是在java中的spring,为了在js中使用依赖注入,didi
首先看看安装命令
npm install didi
这个时候,我看到项目下的package.json
{
"name": "babelwebpack",
"version": "1.0.0",
"description": "babel webpack ingegraty",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"pack": "webpack",
"publish": "webpack-dev-server --output-public-path=/dev/"
},
"keywords": [
"babel",
"webpack"
],
"author": "hk",
"license": "ISC",
"devDependencies": {
"@babel/cli": "^7.18.10",
"@babel/core": "^7.18.13",
"@babel/preset-env": "^7.18.10",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.10.1"
},
"dependencies": {
"babel-loader": "^8.2.5",
"didi": "^9.0.0"
}
}
我再贴出我的webpack.config.js
var path = require('path');
module.exports = {
entry: {
/** 源代码根路径 */
app: './src/main.js'
},
output: {
/** 这里配置的是webpack的打包输出路径 */
path: path.resolve(__dirname, 'dev'),
filename: 'main_bundle.js'
},
mode:'development',
module: {
rules: [
{
test: /\.js$/,
include: path.resolve(__dirname, 'src'),
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
]
},
devServer: {
static: {
/**这里配置的开发服务器的根路径 */
directory: path.join(__dirname, './public'),
},
hot: true,
compress: true,
port: 9999,
},
};
好了,我要开始使用didi
首先我定义三个组件:
const {Injector} =require('didi');
/*
* 定义一个Car组件,这个Car组件依赖于engine组件
*/
function Car(engine) {
this.start = function() {
engine.start();
};
}
/**
* 定义一个Engine组件,同时这个Engine组件依赖于power组件
*/
function createPetrolEngine(power) {
return {
start: function() {
console.log('Starting engine with ' + power + 'hp');
}
};
}
// define a (didi) Car module,定义一个CarModule,这个模块由三个组件构建
// it declares available components by name and specifies how these are provided
const carModule = {
//请求Car组件的时候,依赖注入器会调用Car的构造函数来创建组件
// asked for 'car', the injector will call new Car(...) to produce it
'car': ['type', Car],
//请求Engine组件的时候,依赖注入器会调用工厂方法来创建组件
// asked for 'engine', the injector will call createPetrolEngine(...) to produce it
'engine': ['factory', createPetrolEngine],
//请求power组件,依赖注入器会通过复制一个value值来创建。
// asked for 'power', the injector will give it number 1184
'power': ['value', 1184] // probably Bugatti Veyron
};
// instantiate an injector with a set of (didi) modules
const injector = new Injector([
carModule
]);
//使用依赖注入器来检索组件并调用组件的API
// use the injector API to retrieve components
injector.get('car').start();
//使用依赖注入器的invoke函数来注入相应的组件
// ...or invoke a function, injecting the arguments
injector.invoke(function(car) {
console.log('started', car);
car.start();
});
大家注意以上代码,我们需要指出几个概念,首先理解什么是组件
,什么是模块
,什么是依赖注入加载器
。
组件可以是一个类,一个函数,甚至是一个值,在以上的代码中,有一个叫做Car
的组件,一个叫做Engine
的组件,以及一个叫做power
的组件,而这三个组件又构成了一个模块,叫做carModule
,这个模块通过依赖注入加载器加载以后,我就可以使用这些组件啦。
使用组件的方式有两种,第一种通过调用get()方法拿到组件以后,再使用。
另一种是通过调用invoke
方法,通过一个函数来获取依赖注入参数,然后再使用。大家可以运行代码试试效果,不过呢,这里有个小问题就是,只有在编辑状态的时候才能运行代码,而且只支持node
的require
引入,不知道这个部分以后是否可以优化。
我们再举一个例子
const {Injector} =require('didi');
class BubType{
constructor() {
this.name = 'bub-value';
}
}
function BuzType() {
this.name = 'buz-value';
}
/**
* 在一个模块定义了四个组件
*/
const newInjector = new Injector([
{
foo: [
'factory',
function() {
return 'foo-value';
}
],
bar: ['value', 'bar-value'],
bub: ['type', BubType],
buz: ['type', BuzType]
}
]);
console.log('foo:',newInjector.get('foo'));
console.log('bar:',newInjector.get('bar'));
console.log('bub:',newInjector.get('bub'));
console.log('buz:',newInjector.get('buz'));
在这里,我们可以得出一个小小的结论就是:Injector
的构造函数是一个数组对象,数组中的每个对象实际上是会生成一个模块,同时产生组件的方式有三类:分别对应三种不同的key值,它们是factory,type,value
这里我们大概理解了基本的用法了吧,其实这个简单的框架为我们组织前端的代码提供了很好的组织方式,能够让我们的代码更加模块化。欢迎大家一起讨论学习。