新手也能看懂的angular的Inject原理

看@inject可以知道,inject需要传入一个InjectionToken类,该类需要传入providedIn和factory函数,代码如下:

export declare class InjectionToken<T> {
   
    protected _desc: string;
    readonly ɵprov: never | undefined;
    constructor(_desc: string, options?: {
   
        providedIn?: Type<any> | 'root' | 'platform' | 'any' | null;
        factory: () => T;
    });
    toString(): string;
}

所以就有了这段代码:

const Test = new InjectionToken<any>('test',{
   
  providedIn:'root',
  factory:()=>'12465'
})

随后我就将Test传入了@Inject,并打印传出的值showTest

export class DragDirective {
   
  constructor(
    @Inject(PLATFORM_ID) private platformId,
    @Inject(Test) private showTest,
    ) {
   
    console.log(this.showTest);
  }
}

在这里插入图片描述

可以看到,打印的值就是factory函数的返回值,由此我们可以得出结论@inject所处理的逻辑都是放在factory函数中。

那么这种方式适用于那些情况呢?比如判断是否为浏览器PLATFORM_ID,类似于该类独立于你的代码,可以被注入任何地方都可以用这种@inject的方式。那么执行时机是什么时候呢?我们来打印一下。

const SET_TOKEN = new InjectionToken<any>('存储固定token',{
   
  providedIn:'root',
  factory:()=>{
   
    console.log('执行inject');
    window.localStorage.setItem('token','123465')
  }
})
export class DragDirective {
   
  constructor(
    @Inject(SET_TOKEN) private showTest,
    ) {
   
    // console.log(this.showTest);
  }
}

在这里插入图片描述
可以发现在被注入的时候就已经执行了,接下来带大家模仿下angular的PLATFORM_ID执行过程,直接上代码:

const PLATFORM_MY = new InjectionToken<any>('获取环境', {
   
  providedIn: 'root',
  factory: () => {
   
    console.log('执行inject');
    const ua = navigator.userAgent.toLowerCase()
AngularJS 中,使用 $injector 服务来注入依赖项时,$injector 会根据依赖项的名称来查找相应的服务,并将服务的实例注入到需要注入依赖项的函数中。 在使用 $inject 属性来指定依赖项的名称时,$injector 会将 $inject 属性中指定的依赖项名称与需要注入依赖项的函数的参数列表进行匹配。如果匹配成功,则会将相应的服务实例注入到需要注入依赖项的函数中。 例如,以下代码定义了一个名为 myController 的控制器: ```javascript angular.module('myModule', []) .controller('myController', ['$scope', '$http', function($scope, $http) { // 使用 $scope 和 $http 服务 }]); ``` 在上面的代码中,$injector 会按照 $inject 属性中指定的依赖项名称来查找相应的服务实例,并将 $scope 和 $http 服务的实例注入到匿名函数中。 需要注意的是,$inject 属性中指定的依赖项的名称必须与需要注入依赖项的函数的参数名称一致,否则 $injector 就无法正确地将服务实例注入到函数中。 除了使用 $inject 属性来指定依赖项的名称之外,我们还可以使用函数的 toString() 方法来获取函数的源码,然后通过正则表达式来解析函数的参数列表,并将参数名称作为依赖项的名称进行注入。例如: ```javascript angular.module('myModule', []) .controller('myController', function($scope, $http) { // 使用 $scope 和 $http 服务 }); // 解析函数参数列表的正则表达式 var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; // 获取函数的源码 var controllerSource = myModule._invokeQueue[0][2][1].toString(); // 通过正则表达式解析函数的参数列表 var matches = controllerSource.match(FN_ARGS); var argNames = matches[1].split(',').map(function(argName) { return argName.trim(); }); // 使用 $injector 服务手动注入依赖项 myModule.controller('myController', argNames.concat(function($scope, $http) { // 使用 $scope 和 $http 服务 })); ``` 在上面的代码中,我们通过获取 myController 控制器的源码,并使用正则表达式解析出参数列表中的参数名称,然后再手动调用 $injector 服务来注入依赖项。虽然这种方式比较繁琐,但是在某些情况下,比如需要动态地创建控制器时,可能会比较有用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Young soul2

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

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

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

打赏作者

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

抵扣说明:

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

余额充值