How to understand angular routing (reproduced)

   Reprinted from: http://blog.csdn.net/qq_20448859/article/details/51994455

1 Introduction

The AngularJS routing mechanism is provided by the ngRoute module, which allows us to decompose the view into a layout and a template view, and dynamically load the template view into the layout according to the change of url, thereby realizing the page jump function of the single-page application.

2. url in AngularJS

The # number is added to the URL of the single-page WEB application. The # number represents a position of the web page, and all content on the right side is the identifier used to mark the position. The # and the following content are called hash fragments in the url, and they will not be sent to the server. The following three urls all request the same address from the server. If you only change the content after the # sign, refreshing will not cause the page to be reloaded.

3. Routing use

1) Import files and inject dependencies

Since version 1.2, AngularJS has stripped ngRoutes from the core code to become an independent module. Therefore, we need to install and inject the dependency on ngRoute in the module declaration in order to use the routing function normally in the AngularJS application.

<script src="angular-route.min.js"></script>
var app = angular.module("myApp",['ngRoute']);
  • 1
  • 2

2) Create a layout template

The reason to create a layout template is to tell AngularJS where to render the layout. With the ng-view command, we can specify exactly where the template view is rendered in the DOM.

<div ng-app="myApp">
    <a ng-href="#/music">音乐</a>
    <a ng-href="#/movie">电影</a>
    <a ng-href="#/novel">小说</a>
    <a ng-href="#/other">其他</a>
    <div ng-view></div>
</div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3) Create some template views

myMusic.html

<p>这里是音乐界面啦</p>
  • 1

myMovie.html

<p>这里是电影界面啦</p>
  • 1

myNovel.html

<p>这里是小说界面啦</p>
  • 1

home.html

<p>我是首页界面</p>
  • 1

4) Define the routing table

app.config(['$routeProvider',function($routeProvide) {
    $routeProvide
        .when('/',{templateUrl:"home.html"})
        .when('/music',{templateUrl:"myMusic.html"})
        .when('/movie',{templateUrl:"myMovie.html"})
        .when('/novel',{templateUrl:"myNovel.html"})
        .otherwise({redirectTo:'/'});
}]);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4. In-depth

1) Services and instructions involved

  • $ routeProvider is used to define the routing table, we will use the two methods inside when and otherwise.
  • $ routeParams is used to save the parameters in the address bar, and also provides the ability to wild-type a certain type of address.
  • $ location is used to analyze and process url.
  • $ ng-view is used to specify the area to load the template view.

2) Detailed explanation of $ location.path ()

如果没有参数,返回当前路径,即#号后的内容;也可以传入字符串,将当前路径修改为字符串的内容,并触发路由变化。
假设当前url:http://localhost:63342/RouteDemo/index.html#/

//返回'/'
$location.path(); 
//将当前url修改为:http://localhost:63342/RouteDemo/index.html#/music
$locaiton.path('/music'); 
//返回'/music'
$locaiton.path();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3)when及otherwise详解

when方法能够接收两个参数,第一个参数是路由路径,这个路径会与$location.path()的值进行匹配,如果没有任何一个when方法匹配到,那么将会执行otherwise方法。第二个参数是配置对象,它的六个属性分别是controller,template,templateUrl,resolve,redirectTo,reloadOnSearch。

  • controller 
    该属性值可以是一个字符串,也可以是一个函数。如果是字符型,则会搜索相应的控制器,如果是函数,那么该函数代表控制器(可以用controllerAs为控制器命名或起别名)。控制器会与路由所创建的作用域关联在一起,并且转到该路径时都会执行一次控制器中的内容。
//每次路径变为/music触发路由变化时都会执行一次控制器中的内容
app.config(['$routeProvider',function($routeProvide) {
    $routeProvide.when('/music'{templateUrl:"myMusic.html",controller:"myController"})           
}]);
app.controller('myController',function($scope) {
    console.log("123");
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • controllerAs 
    给controller属性值代表的控制器起个别名,以便之后引用。
  • template 
    值是一个字符串,代表一个Html模板,AngularJS会拿该模板来渲染。
  • templateUrl 
    值是一个字符串,代表一个存着Html模板的路径,AngularJS会拿该路径下的Html模板来渲染。
  • resolve 
    值是一个对象,该对象属性名是可以注入到控制器的依赖,属性值可包含下列内容。
类型 含义
字符串 代表要注入的服务名称,依赖名为属性名
函数 返回值为promise对象,控制器会等待promise执行完毕将success函数中的response参数注入到控制器,依赖名为属性名

只有当resolve对象里所有promise对象执行完毕后才会注入到控制器,此时才会发生路由变化,因此可以解决页面闪烁问题(加载页面后才获取到数据去更新视图)。我们来看看对比,下面这个例子控制器注入的a是自定义的myService服务,注入的b则是从服务器端获取到的数据。 
test.html代码如下。

<p>我是测试界面 {{ name }}</p>
<div ng-repeat="name in list">{{ name }}</div>
  • 1
  • 2

index.html代码如下。

<body ng-app="myApp">
    <div ng-app="myApp">
        <a ng-href="#/test">测试</a>
        <div ng-view></div>
    </div>
    <script>
        var app = angular.module("myApp",['ngRoute']);
        app.value("myService","张三");
        app.config(['$routeProvider',function($routeProvide) {
            $routeProvide
                .when('/test',{templateUrl:"test.html",
                    controller:function($scope,a,b) {
                        $scope.name = "你好"+a;
                        $scope.list = b.data;
                    },
                    resolve:{
                        a:"myService",
                        b:function($http,$timeout) {
                            var promise =  $timeout(function() {
                                return $http.get("http://localhost:3000/person");
},3000);
                            return promise;
                    }
            }});
        }]);
    </script>
</body>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

如果直接在控制器而不是resolve中请求,则index.html代码如下。

<body ng-app="myApp">
    <div ng-app="myApp">
        <a ng-href="#/test">测试</a>
        <div ng-view></div>
    </div>
    <script>
        var app = angular.module("myApp",['ngRoute']);
        app.value("myService","张三");
        app.config(['$routeProvider',function($routeProvide) {
            $routeProvide
                    .when('/test',{templateUrl:"test.html",
                    controller:function($scope,$http,$timeout,a) {
                        $scope.name = "你好"+a;
                        var promise =  $timeout(function() {
                            return $http.get("http://localhost:3000/person");
                        },3000);
                        promise.then(function(response) {
                            $scope.list = response.data;
                        });
                    },
                    resolve:{
                        a:"myService"
                    }});
        }]);
    </script>
</body>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

两者效果如下,可以看到写在控制器中的代码不仅需要自己处理逻辑(控制器不推荐写太复杂的逻辑)从promise的success function中取得repsonse参数,而且页面加载不一致,服务器获取的数据在获得后才加载,而在resolve中写,只有等promise执行完毕后才会跳转,然后同步加载整个页面。

这里写图片描述 这里写图片描述 
- redirectTo 
值是一个字符串或一个函数,该属性写在otherwise中,代表着在when中找不到相应路径时的重定向。如果是字符串,路径会被替换成该值,如果是函数,它有三个参数,第一个是当前路径的路由参数,第二个是当前路径,第三个当前Url的查询串,路径会被替换成该函数的返回值,替换后都会触发路由变化。 
- reloadOnSearch 
值是一个布尔值,为true的时候$location.search()发生变化时就会重新加载路由,location.search是从当前URL的?号开始(包括?号)的字符串。

4)$routeParams

  我们可以在路由参数的前面加上:号,AngularJS会把它解析出来并传递给$routeParams。 
  下面的例子中我们将123456传给value,AngularJS把其解析出来,在$routeParams中添加一个名为value的键,值为123456,我们可以将该服务注入到控制器中使用。 
  test.html代码如下。

<p>我是测试界面 {{ display }}</p>
  • 1

  index.html代码如下。

<body ng-app="myApp">
    <div ng-app="myApp">
        <a ng-href="#/test/123456">测试</a>
        <div ng-view></div>
    </div>
    <script>
        var app = angular.module("myApp",['ngRoute']);
        app.config(['$routeProvider',function($routeProvide) {
            $routeProvide
                .when('/test/:value',{templateUrl:"test.html",
                    controller:function($scope,$routeParams) {
                        $scope.display = $routeParams.value;
                }});
        }]);
    </script>
</body>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

这里写图片描述

5)路由事件

  $route服务在路由过程中的每个阶段都会触发不同的事件,可以为这些事件设置监听器并做出响应。路由事件都是系统自动从$rootScope广播下去的,我们最好的做法是在$rootScope中监听,而最佳设置的地方就是run方法,可以保证不会漏掉任何路由变化。 
  下面是四种不同的路由事件。

  • $routeChangeStart 
    AngularJS在路由改变之前就会广播此事件,在广播后,路由会开始加载路由变化所需要的所有依赖,并且模板和resolve键中的promise都会被resolve。
  • $routeChangeSuccess 
    在路由的依赖加载,且resolve键中所有promise都resolve了就会广播此事件。
  • $routeChangeError 
    在resolve键中任何一个promise被拒绝或者失败后会广播此事件,也就是说,此事件与$routeChangeSuccess互斥。
  • $routeUpdate 
    在reloadOnSearch属性设置为false的情况下,重新使用某个控制器的实例会广播该事件。

    下面一个例子演示了服务器开启和未开启时的各个事件发生的顺序。

<body ng-app="myApp">
    <div ng-app="myApp">
        <a ng-href="#/test">测试</a>
        <div ng-view></div>
    </div>
    <script>
        var app = angular.module("myApp",['ngRoute']);
        app.config(['$routeProvider',function($routeProvide) {
            $routeProvide
                .when('/test',{templateUrl:"test.html",
                controller:function() {
                    console.log("controller");
                },
                resolve:{
                    myData:function($http,$timeout) {
                        var promise =  $timeout(function() {
                            return $http.get("http://localhost:3000/person");
                        },3000);
                        console.log("resolve");
                        return promise;
                    }
                }
            });
        }]);
        app.run(function($rootScope,$location) {
            $rootScope.$on('$routeChangeStart',function() {
                console.log("$routeChangeStart");
            });
            $rootScope.$on('$routeChangeSuccess',function() {
                console.log("$routeChangeSuccess");
            });
            $rootScope.$on('$routeChangeError',function() {
                console.log("$routeChangeError");
            });
            $rootScope.$on('$routeUpdate',function() {
                console.log("$routeUpdate");
            });
        });
    </script>
</body>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

这里写图片描述 这里写图片描述

发布了7 篇原创文章 · 获赞 5 · 访问量 4120

Guess you like

Origin blog.csdn.net/blue_heart_/article/details/78709249