Angular 1.x和ES6的结合

471 查看

在Web前端技术飞速发展的今天,Angular 1.x可以说是一个比较旧的东西,而ES6是新生事物。我们想要把这两个东西结合起来,感觉就好像“十八新娘八十郎,苍苍白发对红妆。”但这件事的难度也并不大,因为我们最终是要把ES6构建成ES5代码,而ES5代码是可以很容易和Angular 1.x协作的。

不过,为什么我们要干这件事呢?

这篇文章中,我提到过:

尽管在整个前端开发圈中,大家并不是很欢迎Angular,而且很多人认为它的1.x版本已经衰落,但我跟 @小猪有个观点是一致的,那就是:“在企业开发领域,ng1的应用才方兴未艾”,也就是说,它在这个领域其实还是上升阶段。

所以,在不少场合下,它还是要承载一些开发工作,部分老系统的逐步平滑迁移也是比较重要的。

做这件事的另外一个意图是:虽然未来的框架选型会有不少争议,但有一点毋庸置疑,那就是业务JS代码的全面ES6或者TS化,这一点我们现在就可以着手去做,并且可以尽量把数据和业务逻辑层实现成框架无关的形式。

这篇里大致讲了点对这方面的考虑。

模块机制

Angular 1.x的module机制是比较别扭的,也是一种框架私有的模块机制,所以,我们需要淡化这层东西,具体的措施是:

  • 把各功能模块的具体实现代码独立出来
  • module机制作为一个壳子,对功能模块进行包装
  • 每个功能分组,使用一个总的壳子来包装,减少上级模块的引用成本
  • 每个壳子文件把module的name属性export出去

举例来说,我们有一个moduleA,里面有serviceA,serviceB,那么,就有这样一些文件:

serviceA的实现,service/a.js

serviceB的实现,service/b.js

moduleA的壳子定义,moduleA.js

存在一个moduleB要使用moduleA:

注意,这里为什么我们要export module的name呢?这是为了这个module的引用者方便,如果某个module改名了,所有依赖它的module可以不修改代码。

在这里我们可以看到,a.js,b.js,moduleA.js这三个文件,只有moduleA是作为一次性的配置项,而a和b可以尽量实现成框架无关的代码,这样将来的迁移代价会比较小。

service,factory,controller,filter

在Angular 1.x里面,有factory和service两个概念,其实这两者可以替换,service传入的是构造函数,通过new创建出实例,而factory传入的是工厂函数,通过对这个工厂函数的调用而创建实例。

所以,如果要使用ES6代码来编写这个部分,也就很自然了:

serviceA的实现,service/a.js

serviceA的模块包装器moduleA的实现

factoryA的实现,factory/a.js

factoryA的模块包装器moduleA的实现

注意看这个例子中,FactoryA函数的返回结果是new EntityA,在实际项目中,这里不一定是通过某个实体类创建的,也可能是直接一个对象字面量: