推荐使用:BottleJS - 轻量级依赖注入微容器

推荐使用:BottleJS - 轻量级依赖注入微容器

bottlejsA powerful dependency injection micro container for JavaScript applications项目地址:https://gitcode.com/gh_mirrors/bo/bottlejs

BottleJS Logo

BottleJS 是一款强大而小巧的依赖注入容器。它提供了延迟加载、中间件钩子、装饰器以及灵感源自AngularJS模块API和PHP库Pimple的简洁API。如果你喜欢构建组件堆栈而不是全功能框架、喜欢松耦合对象和依赖注入、喜欢直观的API,以及尝试新事物,那么BottleJS将是你不二的选择。

支持环境

BottleJS兼容IE9及以上及所有ECMAScript 5合规浏览器。

安装

BottleJS可用于浏览器或Node.js应用。你可以通过Bower或NPM进行安装:

$ bower install bottlejs
$ npm install bottlejs

此外,它也托管在cdnjs上,可以直接用于你的HTML文件中:

<script src="https://cdnjs.cloudflare.com/ajax/libs/bottlejs/2.0.1/bottle.min.js"></script>

快速入门

让我们从一个简单的例子开始:使用Bottle#service注册服务。假设我们有一个服务对象构造函数:

var Beer = function() { /* 啤酒服务,好喝! */ };

只需以下几步就可以将其注册到Bottle中:

var bottle = new Bottle();
bottle.service('Beer', Beer);

当你需要这个服务实例时,访问bottle.container.Beer即可:

bottle.container.Beer;

简单明了,但背后却发生了这些:

  1. Bottle创建了一个包含工厂函数的提供者。
  2. 当首次访问bottle.container.Beer时,Bottle会查找提供者并执行工厂方法来构建和返回啤酒服务。
  3. 提供者和工厂被删除,bottle.container.Beer属性设置为啤酒服务实例。之后的访问只是一个简单的属性获取。

注入依赖项

如果啤酒服务有依赖怎么办?比如:

var Barley = function() {};
var Hops = function() {};
var Water = function() {};
var Beer = function(barley, hops, water) { /* 啤酒服务,好喝! */ };

你可以这样注册带有依赖的服务:

var bottle = new Bottle();
bottle.service('Barley', Barley);
bottle.service('Hops', Hops);
bottle.service('Water', Water);
bottle.service('Beer', Beer, 'Barley', 'Hops', 'Water');

现在,当你访问bottle.container.Beer时,Bottle会懒加载所有依赖,并将它们注入到啤酒服务实例后再返回。

使用服务工厂

如果你需要更复杂的逻辑来创建服务,可以使用Bottle#factory。工厂函数接收容器作为参数,应返回构造好的服务实例:

var bottle = new Bottle();
bottle.service('Barley', Barley);
bottle.service('Hops', Hops);
bottle.service('Water', Water);
bottle.factory('Beer', function(container) {
    var barley = container.Barley;
    var hops = container.Hops;
    var water = container.Water;

    barley.halved();
    hops.doubled();
    water.spring();
    return new Beer(barley, hops, water);
});

使用服务提供者

这是Bottle的核心部分。以上提到的Bottle#serviceBottle#factory只是提供者的简写形式。通常这两个就足够了,但如有需要对不同环境下的服务进行更精细化控制,可以注册为提供者。通过传递一个构造函数来完成,该构造函数暴露一个$get方法,$get方法用作构建服务的工厂。

var bottle = new Bottle();
bottle.service('Barley', Barley);
bottle.service('Hops', Hops);
bottle.service('Water', Water);
bottle.provider('Beer', function() {
    // 如果当前环境不支持水,我们需要对其进行填充。
    if (waterNotSupported) {
        Beer.polyfillWater();
    }

    // 这是服务工厂。
    this.$get = function(container) {
        var barley = container.Barley;
        var hops = container.Hops;
        var water = container.Water;

        barley.halved();
        hops.doubled();
        water.spring();
        return new Beer(barley, hops, water);
    };
});

装饰器

Bottle支持向提供者管道注入装饰器。装饰器是简单的函数,拦截服务在提供商阶段创建后,但首次被访问之前。该函数应返回服务,或者替换使用的另一个对象。

var bottle = new Bottle();
bottle.service('Beer', Beer);
bottle.service('Wine', Wine);
bottle.decorator(function(service) {
    // 此装饰器将应用于啤酒和葡萄酒服务。
    service.stayCold();
    return service;
});

bottle.decorator('Wine', function(wine) {
    // 此装饰器仅影响葡萄酒服务。
    wine.unCork();
    return wine;
});

中间件

Bottle中间件类似装饰器,但每次从容器访问服务时都会执行。它们接受服务实例和一个next函数:

var bottle = new Bottle();
bottle.service('Beer', Beer);
bottle.middleware(function(service, next) {
    // 每次服务被访问时都会执行此中间件。
    console.log('服务被访问了!');
    next();
});

bottle.middleware('Beer', function(beer, next) {
    // 只影响啤酒服务。
    console.log('啤酒?不错。给你的调酒师小费吧...');
    next();
});

中间件可以通过向next函数传递错误对象来抛出异常:

var bottle = new Bottle();
bottle.service('Beer', Beer);
bottle.middleware('Beer', function(beer, next) {
    if (beer.hasGoneBad()) {
        return next(new Error('啤酒变质了!'));
    }
    next();
});

// 结果:Uncaught Error: 啤酒变质了!(…)

嵌套瓶子

使用点号表示法,Bottle会为你生成嵌套容器。每个命名部分都将创建一个新的隔离子容器:

var bottle = new Bottle();
var IPA = function() {};
bottle.service('Beer.IPA', IPA);
bottle.container.Beer; // 这是一个新的Bottle.container对象
bottle.container.Beer.IPA; // 服务
bottle.factory('Beer.DoubleIPA', function (container) {
    var IPA = container.IPA; // 注意这里的container是指最近的父容器。
})

子容器是独立的

嵌套容器设计为提供不同包之间的隔离。这意味着你不能在一个不同的父容器编写工厂时访问子容器。

var bottle = new Bottle();
var IPA = function() {};
var Wort = function() {};
bottle.service('Ingredients.Wort', Wort);
bottle.factory('Beer.IPA', function(container) {
    // container是'Beer',不是根容器,因此:
    container.Wort; // undefined
    container.Ingredients.Wort; // undefined
});

API

Bottle

pop(name)

根据名称获取Bottle实例。如果不传参,则直接返回当前实例。调用Bottle构造函数作为函数等同于Bottle.pop()

参数 | 类型 | 详情 :------------------------|:-----------|:-------- name
(可选) | String | 瓶子的名称。如果提供,Bottle将存储内部实例并返回相同名称的实例。

clear(name)

移除指定名字的Bottle实例,如果存在的话。接下来调用Bottle.pop(name)将创建新实例。如果不提供名称,将清除所有命名的内部实例。

一般来说,只有在打算重置瓶子实例以添加新的提供者、装饰器等情况时才调用此方法,如测试初始化。

参数 | 类型 | 详情 :----------------------|:-----------|:-------- name
(可选) | String | 瓶子名称。若提供,将删除内部存储的实例,如果之前曾使用Bottle.pop创建。如果未提供,将删除所有内部存储的实例。

list(container)
prototype.list()
prototype.container.$list()

列出容器上注册的所有常量、值和服务的名称。全局静态版本Bottle.list(bottle.container)必须传入容器。原型版本使用实例的容器,容器版本则使用自身。

返回一个字符串数组。

参数 | 类型 | 详情 :-----------------------|:-----------|:-------- container
(可选) | Object | 一个bottle.container。仅当使用全局静态Bottle.list时必需。原型版本将使用该实例的容器,容器版本将使用自身。

config

全局配置对象。

属性 | 类型 | 默认值 | 详情 :-------------|:-----------|:--------|:-------- strict | Boolean | false | 开启严格模式。目前仅检查自动注入的依赖是否未定义。

Bottle.prototype

decorators

由瓶子实例注册的装饰器集合。参见decorator(name, func)下面的描述。

middlewares

由瓶子实例注册的中间件集合。参见middleware(name, func)下面的描述。

nested

父瓶子实例根据点号表示法注册的嵌套瓶子集合。请参考文档中的“嵌套瓶子”部分。

providerMap

已注册提供者名的集合。Bottle使用此内部结构来确定提供者是否已实例化过。请参阅provider(name, Provider)下方。

deferred

当前瓶子实例注册的延迟函数集合。参见defer(func)下方。

constant(name, value)

向容器添加只读值。

参数 | 类型 | 详情 :---------|:----------|:-------- name | String | 值的名称。 value | Any | 需要注册的值。


BottleJS为你提供了构建现代应用程序所需的灵活性和控制力,无论是在浏览器还是服务器端。其强大的API允许你实现复杂的服务管理,同时也保持代码清晰易懂。立即加入数以千计的开发者,享受BottleJS带给你的便捷开发体验吧!

bottlejsA powerful dependency injection micro container for JavaScript applications项目地址:https://gitcode.com/gh_mirrors/bo/bottlejs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

余靖年Veronica

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值