You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
importinjectorfrom'angular-es-utils/injector';importangularfrom'angular';const$rootScope=injector.get('$rootScope');exportconst$apply=(target,key,descriptor)=>{constfn=descriptor.value;if(!angular.isFunction(fn)){thrownewSyntaxError('Only functions can be @$apply');}return{
...descriptor,value(...args){if(!$rootScope.$$phase){$rootScope.$digest(()=>{fn.apply(this,args);});}}};};classMainCtrl{
@$applytest(){}}
3.$timeout
importinjectorfrom'angular-es-utils/injector';importangularfrom'angular';const$timeout=injector.get('$timeout');exportconst$timeout=(delay=0,invokeApply=true)=>(target,key,descriptor)=>{constfn=descriptor.value;if(!angular.isFunction(fn)){thrownewSyntaxError('Only functions can be @timeout');}return{
...descriptor,value(...args){$timeout(()=>{fn.apply(this,args);},delay,invokeApply);}};};classMainCtrl{
@$timeout(0,false)test(){}}
4.路由配置
使用 UI-Router 去实现应用中的路由,使用装饰器将路由配置与 controller class 进行绑定,当 Angular 声明 module 时,读取对应的路由配置进行路由设置。
importangularfrom'angular';exportconstBefore=(beforeFn)=>(target,key,descriptor)=>{constfn=descriptor.value;if(!angular.isFunction(fn)){thrownewSyntaxError('Only functions can be @Before');}if(!angular.isFunction(beforeFn)){thrownewSyntaxError('Only function can be pass to @Before');}return{
...descriptor,value(...args){args=beforeFn.apply(this,args)||args;returnfn.apply(this,args);}};};exportconstAfter=(afterFn)=>(target,key,descriptor)=>{constfn=descriptor.value;if(!angular.isFunction(fn)){thrownewSyntaxError('Only functions can be @After');}if(!angular.isFunction(afterFn)){thrownewSyntaxError('Only function can be pass to @After');}return{
...descriptor,value(...args){constresult=fun.apply(this,args);returnfn.apply(this,args.unshift(result))||result;}};};
ES 装饰器在 AngularJS 1.x 中的使用
准备
关于 ES 装饰器(decorator) 这个特性,就不在这里详细的介绍了: 更多内容大家可以参考javascript-decorators
简单的总结一下:
ES 的装饰器可以装饰类和类的方法(也可以装饰对象的方法):
1.装饰类的方法
2.装饰类
关于装饰器如何传参,参考上面提到的资料。
使用
因为现有产品需要切换成 ES6(当然这里不单指 ES6 的特性)
在公司 AngularJS1.x 与 ES6 的编码风格中,对 controller 的使用,已经全面使用 class 去实现,这为使用装饰器创造了条件。
1.声明依赖注入
AngularJS 依赖注入显示声明, 可以很好的利用装饰器。请看实现:
当然还有更好的实现,这个大家可以参看 angular-es-utils 中的 inject 实现,非常的巧妙。
如果考虑到继承的情况,angular-es-utils 中的 inject 就不合适了。 另外该 Inject 返回了新的 class 这样会导致一块使用的装饰器,无法获取原构造函数的信息。
最终方案,使用 Proxy 修改 constructor,自动将注入的服务挂载到 controller prototype 上
2.$apply
该实现依赖 angular-es-utils
3.$timeout
4.路由配置
使用 UI-Router 去实现应用中的路由,使用装饰器将路由配置与 controller class 进行绑定,当 Angular 声明 module 时,读取对应的路由配置进行路由设置。
将配置存入一个公共对象中,以 class 名称作为 key(也可以使用 Reflect.defineProperty 看你的浏览支持情况)
封装 AngularJS module 方法,当初始化 module 时,设置路由, 根据 AngularJS + ES6 风格指南,顺便不对外提供 factory 和 filter 方法
5.Mixin
除了使用继承外, 为了简化 controller, 将其它功能通过 Mixin 的方式混入 controller class 中。
6.Before/After
在 AngularJS1.x 结合 ES6 规范中已经弃用了 filter/service/factory 具体原因参考规范中No Service/Filter !!。 $provide.decorator 已经没有应用场景了。此时需要扩展一个 util 类或对象的方法,除了继承外,也可以使用装饰器进行扩展。
7.其他功能
类似 Debounce Bind 等功能,非常有用。这些都可以参考 core-decorators.js
以上装饰器的实现,请参考 https://github.com/hjzheng/angular-utils
最后
装饰器特性不仅可以在不改变原有类或方法的前提下,增加新的功能和特性,另外还可以简化代码的写法,对于编码效率提升非常有用。
The text was updated successfully, but these errors were encountered: