新手也能看懂的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);
  }
}

新手也能看懂的angular的Inject原理_第1张图片

可以看到,打印的值就是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的Inject原理_第2张图片
可以发现在被注入的时候就已经执行了,接下来带大家模仿下angular的PLATFORM_ID执行过程,直接上代码:

const PLATFORM_MY = new InjectionToken<any>('获取环境', {
  providedIn: 'root',
  factory: () => {
    console.log('执行inject');
    const ua = navigator.userAgent.toLowerCase();
    const testUa = (regexp) => regexp.test(ua);
    const testVs = (regexp) =>
      (ua.match(regexp) + '').replace(/[^0-9|_.]/gi, '').replace(/_/gi, '.');
    // 系统
    let system = 'unknown';
    if (testUa(/windows|win32|win64|wow32|wow64/gi)) {
      system = 'windows'; // window系统
    } else if (testUa(/macintosh|macintel/gi)) {
      system = 'osx'; // osx系统
    } else if (testUa(/x11/gi)) {
      system = 'linux'; // linux系统
    } else if (testUa(/android|adr/gi)) {
      system = 'android'; // android系统
    } else if (testUa(/ios|iphone|ipad|ipod|iwatch/gi)) {
      system = 'ios'; // ios系统
    }

    // 系统版本
    let systemVs = 'unknown';
    if (system === 'windows') {
      if (testUa(/windows nt 5.0|windows 2000/gi)) {
        systemVs = '2000';
      } else if (testUa(/windows nt 5.1|windows xp/gi)) {
        systemVs = 'xp';
      } else if (testUa(/windows nt 5.2|windows 2003/gi)) {
        systemVs = '2003';
      } else if (testUa(/windows nt 6.0|windows vista/gi)) {
        systemVs = 'vista';
      } else if (testUa(/windows nt 6.1|windows 7/gi)) {
        systemVs = '7';
      } else if (testUa(/windows nt 6.2|windows 8/gi)) {
        systemVs = '8';
      } else if (testUa(/windows nt 6.3|windows 8.1/gi)) {
        systemVs = '8.1';
      } else if (testUa(/windows nt 10.0|windows 10/gi)) {
        systemVs = '10';
      }
    } else if (system === 'osx') {
      systemVs = testVs(/os x [\d._]+/gi);
    } else if (system === 'android') {
      systemVs = testVs(/android [\d._]+/gi);
    } else if (system === 'ios') {
      systemVs = testVs(/os [\d._]+/gi);
    }

    let platform = 'unknow';
    if (system === 'windows' || system === 'osx' || system === 'linux') {
      platform = 'desktop'; // 桌面端
    } else if (system === 'android' || system === 'ios' || testUa(/mobile/gi)) {
      platform = 'mobile'; // 移动端
    }

    let engine = 'unknow';
    let supporter = 'unknow';
    if (testUa(/applewebkit/gi) && testUa(/safari/gi)) {
      engine = 'webkit'; // webkit内核
      if (testUa(/edge/gi)) {
        supporter = 'edge'; // edge浏览器
      } else if (testUa(/opr/gi)) {
        supporter = 'opera'; // opera浏览器
      } else if (testUa(/chrome/gi)) {
        supporter = 'chrome'; // chrome浏览器
      } else {
        supporter = 'safari'; // safari浏览器
      }
    } else if (testUa(/gecko/gi) && testUa(/firefox/gi)) {
      engine = 'gecko'; // gecko内核
      supporter = 'firefox'; // firefox浏览器
    } else if (testUa(/presto/gi)) {
      engine = 'presto'; // presto内核
      supporter = 'opera'; // opera浏览器
    } else if (testUa(/trident|compatible|msie/gi)) {
      engine = 'trident'; // trident内核
      supporter = 'iexplore'; // iexplore浏览器
    }

    // 内核版本
    let engineVs = 'unknow';
    if (engine === 'webkit') {
      engineVs = testVs(/applewebkit\/[\d.]+/gi);
    } else if (engine === 'gecko') {
      engineVs = testVs(/gecko\/[\d.]+/gi);
    } else if (engine === 'presto') {
      engineVs = testVs(/presto\/[\d.]+/gi);
    } else if (engine === 'trident') {
      engineVs = testVs(/trident\/[\d.]+/gi);
    }

    // 载体版本
    let supporterVs = 'unknow';
    if (supporter === 'chrome') {
      supporterVs = testVs(/chrome\/[\d.]+/gi);
    } else if (supporter === 'safari') {
      supporterVs = testVs(/version\/[\d.]+/gi);
    } else if (supporter === 'firefox') {
      supporterVs = testVs(/firefox\/[\d.]+/gi);
    } else if (supporter === 'opera') {
      supporterVs = testVs(/opr\/[\d.]+/gi);
    } else if (supporter === 'iexplore') {
      supporterVs = testVs(/(msie [\d.]+)|(rv:[\d.]+)/gi);
    } else if (supporter === 'edge') {
      supporterVs = testVs(/edge\/[\d.]+/gi);
    }

    let shell = 'none';
    let shellVs = 'unknow';
    if (testUa(/micromessenger/gi)) {
      shell = 'wechat'; // 微信浏览器
      shellVs = testVs(/micromessenger\/[\d.]+/gi);
    } else if (testUa(/qqbrowser/gi)) {
      shell = 'qq'; // QQ浏览器
      shellVs = testVs(/qqbrowser\/[\d.]+/gi);
    } else if (testUa(/ubrowser/gi)) {
      shell = 'uc'; // UC浏览器
      shellVs = testVs(/ubrowser\/[\d.]+/gi);
    } else if (testUa(/2345explorer/gi)) {
      shell = '2345'; // 2345浏览器
      shellVs = testVs(/2345explorer\/[\d.]+/gi);
    } else if (testUa(/metasr/gi)) {
      shell = 'sougou'; // 搜狗浏览器
    } else if (testUa(/lbbrowser/gi)) {
      shell = 'liebao'; // 猎豹浏览器
    } else if (testUa(/maxthon/gi)) {
      shell = 'maxthon'; // 遨游浏览器
      shellVs = testVs(/maxthon\/[\d.]+/gi);
    } else if (testUa(/bidubrowser/gi)) {
      shell = 'baidu'; // 百度浏览器
      shellVs = testVs(/bidubrowser [\d.]+/gi);
    }

    return Object.assign({
      engine, // webkit gecko presto trident
      engineVs,
      platform, // desktop mobile
      supporter, // chrome safari firefox opera iexplore edge
      supporterVs,
      system, // windows osx linux android ios
      systemVs
     }, shell === "none" ? {} : {
      shell, // wechat qq uc 2345 sougou liebao maxthon baidu
      shellVs
     });
  },
});

export class DragDirective {
  constructor(
    @Inject(PLATFORM_MY) private getPlatForm,
  ) {
    console.log(this.getPlatForm);
  }
}

新手也能看懂的angular的Inject原理_第3张图片
所以angular的Inject你会玩了吗?

你可能感兴趣的:(angular原理,angular,依赖注入)