AngularJS路由和模板

AngularJS体验式编程系列文章,将介绍如何用angularjs构建一个强大的web前端系统。angularjs是由Google团队开发的一款非常优秀web前端框架。在当前如此多的web框架下,angularjs能脱颖而出,从架构设计上就高人一等,双向数据绑定,依赖注入,指令,MVC,模板。Angular.js创新地把后台技术融入前端开发,扫去jQuery一度的光芒。用angularjs就像写后台代码,更规范,更结构化,更可控。

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/angularjs-route-template/

AngularJS-route

前言

如果想开发一款类似gmail的web应用,我们怎么做呢?

以jQuery的思路,做响应式的架构设计时,我们要监听所有点击事件,通过事件函数触发我们加载数据,提交,弹框,验证等的功能;以 AngularJS的思路,做声明式的架构设计时,我们通过指令和路由先设定好,什么样的操作干什么事情,等事件发生时,程序就会知道该干什么了。

今天说一下,AngularJS是如何实现前端路由功能的!

目录

  1. AngularJS路由介绍
  2. 路由的代码实现
  3. 实现效果截图

1. AngularJS路由介绍

AngularJS路由功能是一个纯前端的解决方案,与我们熟悉的后台路由不太一样。后台路由,通过不同的URL会路由到不同的控制器上(controller),再渲染(render)到页面(HTML)。AngularJS的前端路由,需求提前对指定的(ng-app),定义路由规则(routeProvider),然后通过不同的URL,告诉(ng-app)加载哪个页面(HTML),再渲染到(ng-app)视图(ng-view)中。

AngularJS的前端路由,虽然URL输入不一样,页面展示不一样,其实完成的单页(ng-app)视图(ng-view)的局部刷新。这样来看,AngularJS做单页应用就有点标配的感觉了。

从这个角度想想,要实现一个gmail的应用,真的就不难了。

2. 路由的代码实现

理论不多说了,直接上代码!! 还是基于我们之前用yeoman构建的项目

业务场景:论坛功能,帖子列表页(list.html) 和 帖子内容页(detail.html)。

代码文件:

  • 1. 增加:app/demo-route.html
  • 2. 增加:app/views/route/list.html
  • 3. 增加:app/views/route/detail.html
  • 4. 修改: app/scripts/app.js
  • 5. 修改: app/scripts/controllers/main.js

1). 增加:app/demo-route.html
这个文件是主页面(ng-app),包含视图(ng-view)

<!doctype html>
<head>
<meta charset="utf-8">
<title>route</title>
</head>
<body ng-app="routeApp">
<h1>Route Demo index</h1>

<div ng-view></div>

<script src="bower_components/angular/angular.js"></script>
<script src="scripts/app.js"></script>
<script src="scripts/controllers/main.js"></script>
</body>
</html>

2). 增加:app/views/route/list.html
这个页面是布局模板,是HTML的代码片段。包括了一组ID的列表,通过ID列表的链接,可以进入到ID的详细页面。


<hr/>
<h3>Route : List.html</h3>

<ul>
<li ng-repeat="id in [1, 2, 3 ]">
<a href="#/list/{{ id }}"> ID{{ id }}</a>
</li>
</ul>

3). 增加:app/views/route/detail.html
这个页面是布局模板,是HTML的代码片段。通过ID访问,包含ID号, (ID的文章内容)


<hr/>
<h3>Route <span style="color: red;">{{id}}</span>: detail.html </h3>

4). 修改: app/scripts/app.js
这个是ng-app文件的定义,我们在demo-route.html中定义了routeApp,在这里需要声明。


var routeApp = angular.module('routeApp',[]);
routeApp.config(['$routeProvider',function ($routeProvider) {
      $routeProvider
      .when('/list', {
        templateUrl: 'views/route/list.html',
        controller: 'RouteListCtl'
      })
      .when('/list/:id', {
          templateUrl: 'views/route/detail.html',
          controller: 'RouteDetailCtl'
      })
      .otherwise({
        redirectTo: '/list'
      });
}]);

在routeApp模块中,我们定义了路由和布局模板。routeApp的默认URL是/list,即http://localhost:9000/demo-route.html#/list。 跳转详细页的路由是/list/:id,id为参数。

同时,/list的布局模板是views/route/list.html,属于RouteListCtl的控制器管理空间。

5). 修改: app/scripts/controllers/main.js
这个文件定义控制器controller。


routeApp.controller('RouteListCtl',function($scope) {
});
routeApp.controller('RouteDetailCtl',function($scope, $routeParams) {
    $scope.id = $routeParams.id;
});

分别对应该路由中的两个控制器声明。

程序写好,我们打开浏览器看效果。

3. 实现效果截图

别忘了用下面命令,启动程序。

grunt server

浏览器被自动打开,默认出的是http://localhost:9000/demo-route.html#/list, “#/list”是被redirectTo转向的结果。

AngularJS-route1

点击ID2的链接。

AngularJS-route2

页面被刷新了,出了detil的页面。同时,我们注意观察,页面没有整个刷新,而在视图中(ng-view)做的局部刷新。因为,chrome的开发工具的监控中,只是看到detail.html被加载。

我们再浏览地址栏中,输入212

http://localhost:9000/demo-route.html#/list/212

AngularJS-route3

观察chrome的开发工具的监控中,没有任何的networking操作。

在浏览地址栏中,再输入原来list的地址

http://localhost:9000/demo-route.html#/list

观察chrome的开发工具的监控,确认没有任何变化!!

从这个实验,我们看到AngularJS纯前端路由的实现思路,配合视图的局部刷新,把业务功能切片后分散到HTML的模板页面中。非常容易地实现了widget。并且,这种widget可重用性会非常高,能大大减少前端代码量。

后端组件化开发思路,流畅的嵌入前端。爽死啦!!!

转载请注明出处:
http://blog.fens.me/angularjs-route-template/

打赏作者

This entry was posted in Javascript语言实践, 架构设计

  • jiyinyiyong

    Angular 觉得好难懂.. View, subView 概念基本都颠覆了
    View 之间的消息传递在 Angular 也找不着对应的,, 似乎都跟不上了

    • 完全后台的开发思路,你有时间了解一个Java的Spring,再学Angular就容易多了。几乎是一个大模子出来的。

      • jiyinyiyong

        想不到会跑这么远.. 印象里 Spring 是后端 MVC 呀

        • Angular这种架构的设计思路,应该源于后端开发架构。

          Spring中也有IOC, DataBinding, Service, Component这些概念都。与Angular基于是一样的设计思路。我曾经也尝试过,用后端架构来设计前端应用,Angular的真的很巧妙!

          相比jQuery也似乎,对应后端架构的消息系统(MQ)。

          • jiyinyiyong

            我的后端开发经验只有 CNodeJS 的 Node 部分代码…
            感觉上, 即便是 Backbone 的 MV* 和后端的 MVC 差距也非常大啊.
            要再看下…

          • 我觉得所有这些概念都是次要的,核心还是写这些代码过程中,我们是不是觉得爽。。。

          • jiyinyiyong

            其实也是对实际的场景, 工具是否合适的问题啦

    • view之间似乎不应该直接传消息~~也许应该用emit来传输或者用某个中介来传输。。。

      • jiyinyiyong

        嗯, Backbone 当中, 嵌套直接传, 否则用中介.. 中介更好..
        Angular 呢?

        • 其实这些都是在实际写项目,开发代码过程中,一步步尝试及感觉的。比如你觉得直接传递或者直接放到$rootScope中觉得太恶心了,你就会想放到某个中间件去,比如搞个service之类的。
          我是觉得backbone搞了半天,没让我觉得fancy在哪里,之前我一直看backbone资料,看了大半年。。资料越看越多。。甚至在翻译Anddy的Backbone Fundametal.及Marionatte的资料。结果大半年还没写出什么自己喜欢的代码。
          而用Angularjs似乎我看完官方文档及一些周边资料没花一周,然后就马上开发出个demo了。而且自己很喜欢这样的代码。

          • jiyinyiyong

            我是因为在维护基于 Backbone 的应用, 一直在体会起功能,
            觉得从应用的思路上, View 之间的嵌套, 事件, 相对非常清晰,
            问题也出在这些清晰的部分都需要手动维护, 甚至消耗性能,,,

            Angular 的话, 没有完全对应的概念, View 和 Model 双向绑定,,
            至于怎么用这个东西来组合成大的应用, 就觉得摸不着路了..
            要说 fancy 的确是 Angular.

  • jia58960

    博主熟悉ui-router吗?希望博主有时间写一个关于ui-router的用法。。。

  • binger

    直接刷新浏览器会出错是什么原因,求解答!

  • binger

    点击完列表后,再刷新浏览器报400的错 ,是什么原因

    • 是不是版本的问题?
      最新的angularjs,router单独实现了,直接用文章的代码会不兼容。

  • Tango

    用yo angular构建项目以后,就直接拷贝粘贴你文章中的五个修改的地方,到那时grunt server以后还是跳到了index.html啊,而且ng-view里面的东西根本没有出来,是为什么呢……应该没有其他东西要设置了吧,ng-view和angular route这部分我自己搞了很多试验不知道为什么ng-view就是没东西出来……

    • 可能是因为AngularJS升级的问题,最新版本的AngularJS路由ngRoute需要单独设置。

      $routeProvider,还是可以用,除了要加上ngRoute,还要加上ngSanitize!

      旧的
      var app = angular.module(‘xx’, [‘ui.bootstrap’, ‘ngTable’]);
      app .config([‘$routeProvider’, ‘$locationProvider’, function ($routeProvider, $locationProvider) {

      新的
      var app = angular.module(‘xx’, [‘ui.bootstrap’,’ngRoute’,’ngSanitize’,’ngTable’]);
      app .config([‘$routeProvider’, ‘$locationProvider’, ‘$sceProvider’, function ($routeProvider, $locationProvider, $sceProvider)

      对应再找一下,相关的文档吧。

      • Tango

        上网找了下原来就是少了ngRoute…………谢谢啊……

  • anne

    0.0 那个#弄不明白是哪里来的,吐血,不知道angular 是怎么解析路由的

    • angular已经升级了,本文不适合于最新的版本。
      关于#号的处理,可以参考下文:
      http://blog.fens.me/angularjs-url/

      • anne

        0.0 额 糊里糊涂地,页面弄好了哈。我还是挺喜欢 #,它看起来好酷。。。

  • Hisheng

    为什么点浏览器后退视图没有发生变化呢?

    • angular的ng-route调用了html5的history,后退动作要检查你的angular的怎么用的。

  • Kris Mao

    作者有没有遇到过 用ui-router的时候,在网速慢的情况下,直接url跳转到配置的templateUrl上面去,并且css什么都没有加载,类似下图的情况啊?

    • 有,css有时会没有被加载。尽量让CSS在index.html的首页加载,第一次打开会比较慢,但后面页面跳转会很顺畅。

      • 高小红

        我配置的根本就点击不了,不知道是哪里弄错了吗?求指导,谢谢!

        • Angular新版本,要用ngRoute,在angular.module中增加ngRoute的配置,即可。

          var app = angular.module(‘xx’, [‘ui.bootstrap’,’ngRoute’,’ngSanitize’,’ngTable’]);
          app .config([‘$routeProvider’, ‘$locationProvider’, ‘$sceProvider’, function ($routeProvider, $locationProvider, $sceProvider)

          • 高小红

            好像和我描述的不太一样啊!可以加qq请教一下吗?我的qq:2371381048 谢谢!

          • 抱歉回复晚了,你可以加QQ群383275651,进行交流。谢谢。

  • Kris Mao

    接上回复

  • sdfse

    三步四步都写的不错!

    • angular已经升级了,本文对于新版本angular是不太适用的。