Angular2:使用自定义装饰器或注释将提供者注入组件?
Angular2: Injecting a provider into a component using a custom decorator or annotation?
我使用简单的 TabsProvider
:
在 Ionic 2 中隐藏某些 @Page
s(Ionic 2 装饰器)的选项卡
tabs.ts
import { Injectable } from 'angular2/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class TabsProvider {
currentState = new BehaviorSubject<boolean>(true);
public showTabs(){
this.currentState.next(true);
}
public hideTabs(){
this.currentState.next(false);
}
}
tabs组件订阅currentState
,TabsProvider
注入各个页面如下:
sample-page.ts
:
import {Page} from 'ionic-angular';
import { TabsProvider } from './tabs';
@Page({
...
})
export class SamplePage {
tabsProvider: TabsProvider;
constructor(tabsProvider: TabsProvider) {
this.tabsProvider = tabsProvider;
}
onPageWillEnter(){
this.tabsProvider.hideTabs();
}
onPageWillLeave(){
this.tabsProvider.showTabs();
}
}
这段代码几乎都是样板文件,如果我能在装饰器(或注解)中定义这个功能会更清晰,例如:
import { Page } from 'ionic-angular';
import { hideTabs } from './tabs';
@hideTabs()
@Page({
...
})
export class BuyPage {
}
但我无法确定如何注入 TabsProvider 并将 onPageWillEnter
和 onPageWillLeave
方法添加到 SamplePage。
装饰器(或注释)能否以某种方式注入额外的 Angular 提供程序?
到目前为止我到达的最远距离:
在 tabs.ts
:
export function hideTabs() {
return function(cls: any) {
cls.prototype.onPageWillEnter = function() {
this.tabsProvider.hideTabs();
};
cls.prototype.onPageWillLeave = function() {
this.tabsProvider.showTabs();
};
return cls;
}
}
这让我们得到了我们正在寻找的部分内容,但仍然有必要将 TabsProvider
作为特定实例成员导入和注入:
sample-page.ts
import {Page, Events} from 'ionic-angular';
import { hideTabs, TabsProvider } from './tabs';
@hideTabs()
@Page({
...
})
export class SamplePage {
constructor(public tabsProvider: TabsProvider) {
}
}
是否可以将其完全抽象为 @hideTabs()
?
编辑:
选项卡组件的相关部分(对于任何有兴趣实施的人)pages/tabs/tabs.ts
:
import { Page } from 'ionic-angular';
import { TabsProvider } from './tabs';
@Page({
...
})
export class TabsPage {
...
currentState: boolean;
constructor(TabsProvider: TabsProvider) {
TabsProvider.currentState.subscribe((state: boolean) => {
this.currentState = state;
});
}
}
pages/tabs/tabs.html
:
<div [ngClass]="{'hide-tabs': !currentState}">
<ion-tabs>
...
</ion-tabs>
</div>
pages/tabs/tabs.scss
:
.hide-tabs ion-tabbar-section {
display: none;
}
我刚遇到同样的问题,这是我想出的解决方案。一般做法是:
- 使用
Reflect.getOwnMetadata
从class中读取现有的依赖项。
- 添加到依赖项列表
- 创建一个新的构造函数来包装旧的构造函数并处理这些依赖关系。
tabs.ts
:
import TabsProvider from "./tabs";
export function hideTabs() {
return function(cls: Function) : any {
// Save existing onPageWillEnter and onPageWillLeave inplementations
let enter = cls.prototype.onPageWillEnter || function () {};
let leave = cls.prototype.onPageWillLeave || function () {};
// Create new constructor for class
const newCls = function (tabsProvider, ...args) {
this.__hideTabs__tabsProvider = tabsProvider;
return cls.apply(this, args);
}
// Copy prototype to new constructor
newCls.prototype = constructor.prototype;
// Copy metadata to new constructor
let metadatakeys = Reflect.getMetadataKeys(cls);
metadatakeys.forEach(function (key) {
Reflect.defineMetadata(key, Reflect.getOwnMetadata(key, cls), newCls)
});
// Read dependencies list from 'cls', add our own dependency, and write list to 'newCls'
let dependencies = Reflect.getOwnMetadata('design:paramtypes', cls);
dependencies = [TabsProvider].concat(dependencies)
Reflect.defineMetadata('design:paramtypes', params, newCls);
// Define new onPageWillEnter and onPageWillLeave implementation which implement tab show/hide functionality
// and also call the old implementation saved above (if they exist)
newCls.prototype.onPageWillEnter = function() {
this.tabsProvider.hideTabs();
enter.apply(this, arguments);
};
newCls.prototype.onPageWillLeave = function() {
this.tabsProvider.showTabs();
leave.apply(this, arguments);
};
return newCls;
}
}
我还建议将 @hideTabs
装饰器移动到 @Page
装饰器下方
我使用简单的 TabsProvider
:
@Page
s(Ionic 2 装饰器)的选项卡
tabs.ts
import { Injectable } from 'angular2/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class TabsProvider {
currentState = new BehaviorSubject<boolean>(true);
public showTabs(){
this.currentState.next(true);
}
public hideTabs(){
this.currentState.next(false);
}
}
tabs组件订阅currentState
,TabsProvider
注入各个页面如下:
sample-page.ts
:
import {Page} from 'ionic-angular';
import { TabsProvider } from './tabs';
@Page({
...
})
export class SamplePage {
tabsProvider: TabsProvider;
constructor(tabsProvider: TabsProvider) {
this.tabsProvider = tabsProvider;
}
onPageWillEnter(){
this.tabsProvider.hideTabs();
}
onPageWillLeave(){
this.tabsProvider.showTabs();
}
}
这段代码几乎都是样板文件,如果我能在装饰器(或注解)中定义这个功能会更清晰,例如:
import { Page } from 'ionic-angular';
import { hideTabs } from './tabs';
@hideTabs()
@Page({
...
})
export class BuyPage {
}
但我无法确定如何注入 TabsProvider 并将 onPageWillEnter
和 onPageWillLeave
方法添加到 SamplePage。
装饰器(或注释)能否以某种方式注入额外的 Angular 提供程序?
到目前为止我到达的最远距离:
在 tabs.ts
:
export function hideTabs() {
return function(cls: any) {
cls.prototype.onPageWillEnter = function() {
this.tabsProvider.hideTabs();
};
cls.prototype.onPageWillLeave = function() {
this.tabsProvider.showTabs();
};
return cls;
}
}
这让我们得到了我们正在寻找的部分内容,但仍然有必要将 TabsProvider
作为特定实例成员导入和注入:
sample-page.ts
import {Page, Events} from 'ionic-angular';
import { hideTabs, TabsProvider } from './tabs';
@hideTabs()
@Page({
...
})
export class SamplePage {
constructor(public tabsProvider: TabsProvider) {
}
}
是否可以将其完全抽象为 @hideTabs()
?
编辑:
选项卡组件的相关部分(对于任何有兴趣实施的人)pages/tabs/tabs.ts
:
import { Page } from 'ionic-angular';
import { TabsProvider } from './tabs';
@Page({
...
})
export class TabsPage {
...
currentState: boolean;
constructor(TabsProvider: TabsProvider) {
TabsProvider.currentState.subscribe((state: boolean) => {
this.currentState = state;
});
}
}
pages/tabs/tabs.html
:
<div [ngClass]="{'hide-tabs': !currentState}">
<ion-tabs>
...
</ion-tabs>
</div>
pages/tabs/tabs.scss
:
.hide-tabs ion-tabbar-section {
display: none;
}
我刚遇到同样的问题,这是我想出的解决方案。一般做法是:
- 使用
Reflect.getOwnMetadata
从class中读取现有的依赖项。 - 添加到依赖项列表
- 创建一个新的构造函数来包装旧的构造函数并处理这些依赖关系。
tabs.ts
:
import TabsProvider from "./tabs";
export function hideTabs() {
return function(cls: Function) : any {
// Save existing onPageWillEnter and onPageWillLeave inplementations
let enter = cls.prototype.onPageWillEnter || function () {};
let leave = cls.prototype.onPageWillLeave || function () {};
// Create new constructor for class
const newCls = function (tabsProvider, ...args) {
this.__hideTabs__tabsProvider = tabsProvider;
return cls.apply(this, args);
}
// Copy prototype to new constructor
newCls.prototype = constructor.prototype;
// Copy metadata to new constructor
let metadatakeys = Reflect.getMetadataKeys(cls);
metadatakeys.forEach(function (key) {
Reflect.defineMetadata(key, Reflect.getOwnMetadata(key, cls), newCls)
});
// Read dependencies list from 'cls', add our own dependency, and write list to 'newCls'
let dependencies = Reflect.getOwnMetadata('design:paramtypes', cls);
dependencies = [TabsProvider].concat(dependencies)
Reflect.defineMetadata('design:paramtypes', params, newCls);
// Define new onPageWillEnter and onPageWillLeave implementation which implement tab show/hide functionality
// and also call the old implementation saved above (if they exist)
newCls.prototype.onPageWillEnter = function() {
this.tabsProvider.hideTabs();
enter.apply(this, arguments);
};
newCls.prototype.onPageWillLeave = function() {
this.tabsProvider.showTabs();
leave.apply(this, arguments);
};
return newCls;
}
}
我还建议将 @hideTabs
装饰器移动到 @Page
装饰器下方