如何从 Angular 中的类名中找到组件类的原型并获取该类原型中定义的属性值?

Posted

技术标签:

【中文标题】如何从 Angular 中的类名中找到组件类的原型并获取该类原型中定义的属性值?【英文标题】:How can I find the prototype of component class from class name in Angular and get the value of property defined in that class prototype? 【发布时间】:2018-04-26 04:37:38 【问题描述】:
export class AppSample1Component 
  public propertyWithDefaultValue = 'Lorem ipsum dolor sit amet!';

是否可以在 Angular 中访问组件的类原型?

例如(这个不返回值):

console.log(AppSample1Component.prototype.propertyWithDefaultValue);

如果可能,我如何在路由解析器函数中获取类的原型?

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any 
    const componentType = typeof route.component === 'string' ? route.component : route.component.name;
    console.log('Class name of the component: ', componentType);
    console.log('>>> I want to find the prototype of component class from ActivatedRouteSnapshot and get the value of "propertyWithDefaultValue" property of that class prototype in this section.');

    return new Promise((resolve, reject) => 
        Promise.all([
            this.getData()
        ]).then(
            () => 
                // Init component(s) after prefetch data, etc...
                resolve();
            ,
            reject
            );
    );

您可以查看StackBlitz reproduction of the problem here。


编辑

我提到 Angular 是因为我想了解 Angular 是否有一个内部方法/属性来查找类属性元数据的映射,这允许我在路由器解析器方法中访问类的静态属性。 Angular 知道 route.component.name。所以我认为它可能有一个内部位置可以找到这种元数据。

// Here's an example which shows a minimal use of OOP in my recent javascript projects
const myLib = 
    apply: function (obj, config) 
        if (obj && config && typeof config === 'object')
            for (var p in config)
                obj[p] = config[p];
        return obj;
    ,
    extend: function (sc, bc) 
        var Fn = function () ;
        Fn.prototype = bc.prototype;
        var scpb = sc.prototype;
        var scp = sc.prototype = new Fn();
        scp.constructor = sc;
        if (bc.prototype.constructor === Object.prototype.constructor)
            bc.prototype.constructor = bc;
        myLib.apply(scp, scpb);
        sc.superclass = bc.prototype;
    
;
myLib.textField = function (config) 

;
myLib.textField.prototype = 
    type: 'text'
;

myLib.numberField = function (config) 
	myLib.numberField.superclass.constructor.call(this, config);
;
myLib.numberField.prototype = 
    type: 'number',
    min: 0,
    max: 9999
;
myLib.extend(myLib.numberField, myLib.textField);

const obj1 = new myLib.textField();
const obj2 = new myLib.numberField();

console.group('My old JS way');
console.log(obj1.type, obj2.type);
console.log(myLib.textField.prototype.max, myLib.numberField.prototype.max);
console.groupEnd();

// And here is a demonstration of typescript generated javascript.
// Compiled typescript code generates javascript class as something like below.
// Typescript places the properties to the beginning of the constructor, not to prototype.
// This is why it's not possible to access class prototype directly.
myLib.numberField2 = function () 
    this.type = 'number';
    this.min = 0;
    this.max = 9999;
    //constructor block begin
    //constructor block end
;
const obj3 = new myLib.numberField2();
console.group('Typescript compiled output demonstration');
console.log(obj3.max); // prints 9999

console.log(myLib.numberField2.prototype.max); 
// this prints "undefined" because max property doesn't exist before object creation
console.groupEnd();

【问题讨论】:

你认为为什么会变成AppSample1Component.prototype.propertyWithDefaultValue? typescriptlang.org/play/… 为什么还要设置内置类的原型?扩展它并在自定义子类中设置您的自定义变量。 @yurzui 该语法是我用来访问 javascript 中的类原型属性的语法。这就是为什么我写它来作为一个例子。不是因为我认为它应该变成那种形式。 @omeralper 是的,你是对的。这只是为了演示问题。我正在尝试了解是否可以访问该属性,而我只是将组件的类名放在字符串变量中。 【参考方案1】:

如果我理解您的问题,您是在问“是否可以动态解析给定名称的类?”

您尝试调用此代码的位置以及您是否使用 Angular 似乎与问题无关。

这个问题的一般答案是“不”。类/模块在您的应用程序中不一定具有唯一的名称。例如,您可以在导入它们时重命名它们(例如import LongClassName as LCN from "./long-class-name";)。并且可以有多个同名的类。

假设您已经导入了所有可能需要解析的类,或者正在当前模块中定义它们,您可以使用eval(classNameToResolve).prototype 来获取类原型。但是,出于安全和性能原因,强烈建议不要使用 eval。而且它不适用于所有模块捆绑器,或者如果您缩小代码。

所以,简而言之,不。考虑创建一个允许您进行所需查找的映射,例如

const ALL_MY_CLASSES = 
  ClassA: ClassA,
  ClassB: ClassB

然后您将能够使用ALL_MY_CLASSES[classNameToResolve].prototype 进行查找。当然,您确实需要添加您可能遇到的所有类。

【讨论】:

感谢您的回答。我已经为问题的增强版准备了jsfiddle.net/hallilibrahim/wvm17c8d。

以上是关于如何从 Angular 中的类名中找到组件类的原型并获取该类原型中定义的属性值?的主要内容,如果未能解决你的问题,请参考以下文章

如何从类名中找到 Qt 元对象实例?

Angular - 自动将指令添加到具有给定类的所有元素

如何从 Angular 2 中的数据渲染静态 Angular 组件? [复制]

如何从 Angular 6 中的父组件访问子组件中的表单?

如何从Angular 2中的子组件事件触发父组件中的本地引用?

Java 如何找到全部类的类名