敲碎时间的人的个人专栏
上一篇

Injector框架理解(一)

广告
选中文字可对指定文章内容进行评论啦,→和←可快速切换按钮,绿色背景文字可以点击查看评论额。
大纲

在可测试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方法,通过一个函数来获取依赖注入参数,然后再使用。大家可以运行代码试试效果,不过呢,这里有个小问题就是,只有在编辑状态的时候才能运行代码,而且只支持noderequire引入,不知道这个部分以后是否可以优化。

 

我们再举一个例子

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

这里我们大概理解了基本的用法了吧,其实这个简单的框架为我们组织前端的代码提供了很好的组织方式,能够让我们的代码更加模块化。欢迎大家一起讨论学习。

版权声明:著作权归作者所有。