angular中的那些可替换升级的技术总结

本文介绍了一种在Angular应用中实现服务与组件版本升级的方法,通过配置不同的提供者(Provider),可以在不改动代码的情况下轻松地进行服务或组件的替换与升级。

可服务升级替换的Service

import { Provider } from "@angular/core";

export abstract class Test {
    abstract console(): void;
}

export class TestDefault extends Test {
    console() {
        console.log('test default');
    }
}

export class MyTest extends Test {
    console() {
        console.log('my test');
    }
}

export const TestProvide: Provider = {
    provide: Test,
    useClass: TestDefault
};

export const MyTestProvide: Provider = {
    provide: Test,
    useClass: MyTest
};

复制代码

这样可以选配某个provider

  • 模块中配置使用TestProvide
@NgModule({
  ...,
  providers: [
    TestProvide
  ]
})
复制代码
  • 模块中配置使用MyTestProvide
@NgModule({
  ...,
  providers: [
    MyTestProvide
  ]
})
复制代码

组件中使用TestProvide

@Component({
  ...,
  providers: [TestProvide]
})
export class AppComponent {
  constructor(public test: Test) {
    this.test.console();
  }
}
复制代码

组件中使用TestProvide

@Component({
  ...,
  providers: [MyTestProvide]
})
export class AppComponent {
  constructor(public test: Test) {
    this.test.console();
  }
}
复制代码

比如版本1我们开发了一个TestV1, 升级后可以替换TestV1->TestV2,仅仅改变配置文件即可!

可升级替换的组件

每个组件一个NgModule,NgModule提供替换Ref的static方法forRoot

// 定义组件属性和方法
export abstract class TestRef {
  title: string;
}

export class TestRefDefault {
  title: string = 'default';
}
// 默认
export const TestProvide: Provider[] = [
  {
    provide: TestRef,
    useClass: TestRefDefault
  }
];

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css']
})
export class TestComponent implements OnInit {
  // 绑定到ref属性
  @Input()
  set title(val: any) {
    this.ref.title = val;
  }
  constructor(
    public ref: TestRef
  ) { }
  ngOnInit() {
    console.log(this);
  }
}
复制代码

小总结: 这样有一个弊端就是每个组件共享一个Ref,不能说是弊端,是有一定应用场景的,当所有组件共同操作一个Service时。

升级到factory,隔离Ref,而且可操控父级!

@NgModule({
    exports: [TestComponent],
    declarations: [TestComponent],
})
export class TestModule {
    public static forRoot(providers: Provider[] = TestProvide): ModuleWithProviders {
        return {
            ngModule: TestModule,
            providers: [providers]
        };
    }
}
复制代码
@NgModule({
  imports: [
    CommonModule,
    TestModule.forRoot()
  ],
  declarations: [],
  exports: [TestModule],
  providers: [
    TestProvide
  ]
})
export class SharedModule { }
复制代码
import { Provider } from '@angular/core';
import { Component, OnInit, Input, Optional, SkipSelf } from '@angular/core';
// 工厂方法
export abstract class TestRefFactory {
  abstract create(): TestRef;
}

// 定义组件属性和方法
export abstract class TestRef {
  title: string;
}
// 默认实现
export class TestRefDefault {
  title: string = 'default';
}
// 默认工厂
export class TestRefFactoryDefault extends TestRefFactory {
  create() {
    return new TestRefDefault();
  }
}
// 提供器
export const TestRefFactoryProvider: Provider[] = [{
  provide: TestRefFactory,
  useClass: TestRefFactoryDefault
}];

export function testFactory(factory: TestRefFactory) {
  return factory.create();
}

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css'],
  providers: [
    { provide: TestRef, useFactory: testFactory, deps: [TestRefFactory] }
  ]
})
export class TestComponent implements OnInit {
  // 绑定到ref属性
  @Input()
  set title(val: any) {
    this.ref.title += '-' + val;
  }
  constructor(
    public ref: TestRef,
    // 获取父亲的Ref
    @Optional()
    @SkipSelf()
    public fatherRef: TestRef
  ) { }
  ngOnInit() {
    console.log(this);
  }
}
复制代码

可以获取父Ref,省去不必要的EventEmitter

ref中获取父ref

import { Provider } from '@angular/core';
import { Component, OnInit, Input, Optional, SkipSelf } from '@angular/core';
// 工厂方法
export abstract class TestRefFactory {
  abstract create(father: TestRef): TestRef;
}

// 定义组件属性和方法
export abstract class TestRef {
  title: string;
}
// 默认实现
export class TestRefDefault extends TestRef {
  title: string = 'default';
  constructor(
    public ref?: TestRef
  ) {
    super();
    console.log(this);
  }
}


// 默认工厂
export class TestRefFactoryDefault extends TestRefFactory {
  create(fatherRef?: TestRef) {
    return new TestRefDefault(fatherRef);
  }
}
// 提供器
export const TestRefFactoryProvider: Provider[] = [{
  provide: TestRefFactory,
  useClass: TestRefFactoryDefault
}];

export function testFactory(factory: TestRefFactory, fatherRef?: TestRef) {
  return factory.create(fatherRef);
}

export const testRefProvide = [
  {
    provide: TestRef,
    useFactory: testFactory,
    deps: [
      TestRefFactory,
      [new Optional(), new SkipSelf(), TestRef]
    ]
  }
];

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css'],
  providers: [
    testRefProvide
  ]
})
export class TestComponent implements OnInit {
  // 绑定到ref属性
  @Input()
  set title(val: any) {
    this.ref.title += '-' + val;
  }
  constructor(
    public ref: TestRef,
  ) { }

  ngOnInit() {
  }
}
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值