前端已不止于前端-Angular New Router初体验

@kuitos 2015-08-23 09:45:02发表于 kuitos/kuitos.github.io Angular前端架构

前端已不止于前端-Angular New Router初体验

原文写于 2015-08-07

最近两周在给xxxx跟xxxx两个产品搭前端框架,关于路由这块的技术选型让我犹豫了一下。且让我们先来分析一下

  • ngRoute肯定是最先被pass的,不支持嵌套路由是它的死穴。
  • ui-router在过去半年的使用中,表现的还算不错,提供了一系列足够强大灵活的特性。但是路由必须在app加载之初就被设定好,不能在程序运行过程中动态设置依旧是它的短板(尽管我们可以通过一些trick手段达到动态设置的效果)。

然后想起了angular new router

what is angular new router

ngNewRouter是为angular2设计的新的路由机制,采用纯组件的思路(ng2的设计主旨),同时支持在任意时刻设置路由,具有极大的自由度及可复用性。大约在几个月前,angular团队为ngNewRouter提供了兼容angular 1.4.x的版本。

有这么好的东西还不用,简直是天理不容啊。
基于现有的少的可怜的文档,第一个基于ngNewRouter的项目诞生了。
一步步来看这玩意咋玩吧

  1. setup

    npm install angular-new-router
  2. 路由配置

    /**
     * 路由配置
     */
    AppCtrl.$inject = ['$router'];
    function AppCtrl($router) {
    
      $router.config([
        {path: '/', redirectTo: '/home'},
        {path: '/home', component: 'home'}
      ]);
    
    }

    是的,你没看错,在ngNewRouter中,每一个路由都是一个组件。在ng2中,所有的东西都是组件,UI自然是,但是controller、service甚至是一个路由都是组件。

  3. 配置路由控制器的映射规则
    按照以往ngRoute和ui-router的使用经验,配置路由的同时我们是还需要配置路由的模板及控制器的,即templateUrl 和 Controller,但是第二步并没有发现这样的代码。这是因为ngNewRouter默认路由组件的位置是 ./components/+componentName+/+componentName.html ,而controller的名字默认是 ComponentController
    例如第二步中我们配置的 home 路由组件,则这个路由的模板位置是(应用根目录开始) components/home/home.html , 控制器名字则为 HomeController
    当然这个规则我们也能自己去配置,like this

    /**
     * 初始化 ngNewRouter相关基本配置
     */
    configRouteLoader.$inject = ['$componentLoaderProvider', 'app'];
    function configRouteLoader($componentLoaderProvider, app) {
    
      // 配置路由模板搜索路径
      $componentLoaderProvider.setTemplateMapping(function(name) {
        return app.fileRoot + '/app/viewpoint/' + name + '/' + name + '.html';
      });
    
      // 配置路由控制器命名,如 home-info ---> HomeInfoCtrl
      $componentLoaderProvider.setCtrlNameMapping(function(name) {
    
        return name.split('-').map(function(value) {
          return value[0].toUpperCase() + value.substr(1);
        }).concat(['Ctrl']).join('');
      });
    }
  4. 使用路由
    ngNewRouter提供两个基本指令,ngViewpoint & ngLink ,这么去玩

    <div ng-viewpoint></div>
    
    <a ng-link="marketingCampaign"></a>

    ngViewpoint就类似于ngRoute里的ngView(ui-router里的ui-view).
    ngLink类似于ui-router里的ui-serf

  5. 其他
    如果只能提供这么几个简单的功能那完全没优势可言啊
    嵌套路由,配components即可

    $router.config([
        {path: '/', redirectTo: '/home'},
        {path: '/home', components: {list:'list', detail:'homeDetail'}}
      ]);
    // 既然是组件,那么自然有生命周期一说,对于ngNewRouter中的路由组件而言也一样。
    MyController.prototype.canActivate = function() {
      return this.user.isAdmin;
    };
    
    MyController.prototype.activate = function() {
      this.user.downloadBigFiles();
    };
    
    MyController.prototype.canDeactivate = function() {
      return this.userDataPersisted;
    };

    至于他有啥用,还记得ngRoute和ui-router的resolve配置吗?

写到这里我差不多写不下去了,因为今天又碰到了一个问题,然后研究了半天它的源码网上找了一些资料最后也只能通过绕道的方式解决,然后就开始想,这玩意直接用到项目中是否合适,社区支持太少,官方文档太简洁,毕竟生下来就不是为angular1设计的?
在经过一番思想斗争后,对于技术一向都是有新的就不用旧的这样激进态度的我,最后还是不得不放弃应用ngNewRouter的想法。
然后就在刚才,我在github上看到这个

For now, the code has been moved to angular/angular. APIs are still rapidly changing, so I don't recommend using this in an important production app quite yet.

好吧,我终于可以说服自己不是技术上妥协而是战略上放弃了。。。
虽然好像是绕了一圈又回到了原点,但是基于ngNewRouter还是有了一些新的认识:

  • 对于大型应用而言,组件化必定是趋势。而组件并不仅仅指代的UI层的组件,它还包括逻辑组件。ng2就是这样一个设计思路。另外,有这样一篇文章Thinking in Components

  • ngNewRouter在路由模板及控制器的配置上,采用一种约定的方式,要求使用者必须按照规则命名模板和控制器,这也是后端web框架常用的 约定优于配置 的方式。看了下ngNewRouter这一块的实现,他重写了用于路由组件上的controller注入逻辑。结合最近半年在做的前端框架性的工作,有了一些自己的思考:

    一个面向团队甚至公司的框架,必须是强约束的。框架不同于类库,类库是越灵活越好,而框架则是在封装了大部分细节的基础上,要求使用者必须以某种规则去实现编码的明文规定。只有有了这种强约束,才不至于使得代码质量因为人员的变迁而最后发展成不可控的状态,因为所有人都必须按照指定的方式去写代码。这也是为什么静态语言更适合构建大型项目的原因。一个真正的框架,绝不是仅仅规范了几个目录层级、提供几个组件几个便利的api就完了的。这一块具体应该怎么做,目前还只有零星的一些想法,还有待后续的实践跟检验。