Angular AoT Custom Decorator在静态解析符号值时遇到错误
我创建了一个装饰器来帮助我处理桌面/移动事件
import { HostListener } from '@angular/core'; type MobileAwareEventName = | 'clickstart' | 'clickmove' | 'clickend' | 'document:clickstart' | 'document:clickmove' | 'document:clickend' | 'window:clickstart' | 'window:clickmove' | 'window:clickend'; export const normalizeEventName = (eventName: string) => { return typeof document.ontouchstart !== 'undefined' ? eventName .replace('clickstart','touchstart') .replace('clickmove','touchmove') .replace('clickend','touchend') : eventName .replace('clickstart','mousedown') .replace('clickmove','mousemove') .replace('clickend','mouseup'); }; export const MobileAwareHostListener = ( eventName: MobileAwareEventName,args?: string[],) => { return HostListener(normalizeEventName(eventName),args); }; 问题是当我尝试使用–prod编译时,我收到以下错误 typescript error Error encountered resolving symbol values statically. Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function (position 26:40 in the original .ts file),resolving symbol MobileAwareHostListener in .../event-listener.decorator.ts,resolving symbol HomePage in .../home.ts Error: The Angular AoT build failed. See the issues above 怎么了?我该如何解决这个问题? 解决方法
这意味着错误说明了什么.您正在执行此操作的位置不支持函数调用. Angular内置装饰器
isn’t supported的行为的扩展.
AOT编译(由–prod选项触发)允许静态分析现有代码并用预期的评估结果替换一些部分.这些地方的动态行为意味着AOT不能用于应用程序,这是应用程序的主要缺点. 如果需要自定义行为,则不应使用HostListener.由于它基本上在元素上设置了一个监听器,因此应该使用渲染器提供程序手动完成,这是优于DOM的Angular抽象. 这可以通过自定义装饰器来解决: interface IMobileAwareDirective { injector: Injector; ngOnInit?: Function; ngOnDestroy?: Function; } export function MobileAwareListener(eventName) { return (classProto: IMobileAwareDirective,prop,decorator) => { if (!classProto['_maPatched']) { classProto['_maPatched'] = true; classProto['_maEventsMap'] = [...(classProto['_maEventsMap'] || [])]; const ngOnInitUnpatched = classProto.ngOnInit; classProto.ngOnInit = function(this: IMobileAwareDirective) { const renderer2 = this.injector.get(Renderer2); const elementRef = this.injector.get(ElementRef); const eventNameRegex = /^(?:(window|document|body):|)(.+)/; for (const { eventName,listener } of classProto['_maEventsMap']) { // parse targets const [,eventTarget,eventTargetedName] = eventName.match(eventNameRegex); const unlisten = renderer2.listen( eventTarget || elementRef.nativeElement,eventTargetedName,listener.bind(this) ); // save unlisten callbacks for ngOnDestroy // ... } if (ngOnInitUnpatched) return ngOnInitUnpatched.call(this); } // patch classProto.ngOnDestroy if it exists to remove a listener // ... } // eventName can be tampered here or later in patched ngOnInit classProto['_maEventsMap'].push({ eventName,listener: classProto[prop] }); } } 使用如下: export class FooComponent { constructor(public injector: Injector) {} @MobileAwareListener('clickstart') bar(e) { console.log('bar',e); } @MobileAwareListener('body:clickstart') baz(e) { console.log('baz',e); } } IMobileAwareDirective接口在这里发挥着重要作用.它强制类具有注入器属性,这种方式可以访问其注入器和自己的依赖项(包括ElementRef,它是本地的,显然在根注入器上不可用).此约定是装饰器与类实例依赖项交互的首选方法. class … implements IMobileAwareDirective也可以添加表达性. MobileAwareListener与HostListener的不同之处在于后者接受参数名称列表(包括魔法$event),而前者只接受事件对象并绑定到类实例.这可以在需要时更改. 这是a demo. 此处还有几个问题需要解决.应该在ngOnDestroy中删除事件侦听器.类继承可能存在潜在问题,需要另外测试. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |