zoukankan      html  css  js  c++  java
  • AngularJS(Part 10)--页面导航

    页面导航
        过去,一个URL代表一个页面。但是随着Ajax的兴起,情况发生的很大的变化。不同的内容可以使用同一个URL。这让浏览器中的回退、前进甚至收藏按钮都失去了作用。而AngularJS提供了一套解决方案能够避免这种情况。 怎么解决,有一个小技巧:浏览器不会因为URL中#符号后面的值改变而重新请求页面。(关于#符号,参见另一博文)
        现有如下RESTful的的URL:
            /admin/users/list
            /admin/users/new
            /admin/users/[id]
        我们可以把它们加载URL的#符号后面,就变成了(为了方便,把这种方式先称为hashbang)
            http://localhost/ebis#/admin/users/list
            http://localhost/ebis#/admin/users/new
            http://localhost/ebis#/admin/users/[id].
        浏览器其实是认识上面的URL的。并且认为他们是不同的(所有回退、前进按钮就可用了),但是又不会触发重新加载。
        好吧,万能的HTML5来了,他提供了一个history API可以处理如同
            http://localhost/ebis/admin/users/list
            http://localhost/ebis/admin/users/new
        的请求,并且还不会触发重新加载。(只是服务器端要经过设置)。
        现在AngularJS提供了一个服务,来兼容这两种方式,这就是$location。
        如下URL:
            http://localhost/ebis#/admin/users/list?active=true#bottom
        $location.url()   http://localhost/ebis
        $location.path()   /admin/users/list
        $location.search() {active:true}
        $location.hash()   bottom.
        上面四个方法当没有参数时是get方法;当有参数时是set方法。如$location.hash('top')。当然还有protocol(),host(),port(),absUrl()。这些只是get方法。
    现在看看$location的具体应用,如下代码:
        <div ng-controller="TestController">
            <ul>
                <li><a href="#/admin/users/list">显示用户</a></li>
                <li><a href="#/admin/users/new">添加用户</a></li>
            </ul>
            <div ng-include="selectedRoute.templateUrl">
                <!--Route dependent content gose here -->
            </div>
        </div>
        当然必须还要有Controller
        function TestController($scope,$location){
            var routes={
                        "/admin/users/list":"pages/list.html",
                        "/admin/users/new":"pages/new.html"
                        };
            var defaultRoute=routes["/admin/users/list"];
            
            //仅有上面的还不够,我们还得加个监听器,随时监听URL的变化,就是先面的代码
            $scope.$watch(function(){
                                        return $location.path();
                                    },function(newPath){
                                        $scope.selectedRoute=routes[newPath]||defaultRoute;
                                    });
        }
        最后这个例子并不足够好,实际应用中也不会这么用。实际上我们会用另一个内置的service:$route
    $route 和 $routeProvider
        (通过源码可发现,$route和$routeProvider似乎是一个东西) 在AngularJS配置阶段,可以用$routeProvider来配置Navigation,以实现和上面使用$location一样的功能,并且还会增强。
        angular.module('my-angu',[])
            .config(function($routeProvider){
                $routeProvider
                    .when('/admin/users/list',{templateUrl:'pages/list.html',controller:'UsersController'})
                    .when('/admin/users/new',{templateUrl:'pages/new.html',controller:'NewUserController'})
                    .when('/admin/users/:id',{templateUrl:'pages/edit.html',controller:'EditorController'})
                    .otherwise({redirectTo:'/admin/users/list'});
            });
        @PS:使用此方法,一旦配置,就不能再动态添加其他route了。因为AngularJS只config一次。
        页面HTML如下:
        <div ng-view>
        </div>
        对于Controller:
        .controller('UsersController',function($scope){
                        // logic here
                    })
        .controller('NewUserController',function($scope){
                        // logic here
                    })
        .controller('EditorController',function($scope,$routeParams){
                        var id=$routeParams.id
                        // logic here
                    });
        注意到EditorController中注入了一个新的Service:$routeParams。 他就是用来获取URL中的参数设置。 我们设置的URL是'/admin/users/:id',那么如果请求'/admin/users/12',那么$routeParams.id=12.

    页面转换
        我们可以有两种方式来进行页面转换:
        1.尽快显示新页面,当所需数据从Server返回后在刷新页面
        2.等所有数据都从Server返回并拼装到页面后,再显示页面
        AngularJS默认使用第一种。但是这会产生页面闪烁的问题。(因为短时间内刷新了两次)。所有AngularJS提供了方案使用第二种方式,
        如下:
        .when('/admin/users/:id',{
                                    templateUrl:'pages/edit.html',
                                    controller:'EditorController',
                                    resolve:{
                                            user:function($route,Users){
                                                    return Users.get($route.current.params.id);
                                                 }
                                            }
                                  })
        在EditorController中
        .controller('EditorController',function($scope,user){
                        $scope.user=user;
                    });
        resolve中的属性function可以返回Javascript对象,还有promise。如果返回的是promise,AngularJS会等待promise resolve后才改变URL。
        那么还可以有如下代码:
            resolve:{
                    delay:function($q,$timeout){
                            var delay = $q.defer();
                            $timeout(delay.resolve, 1000);
                             return delay.promise;
                         }
                    }
        他的效果是一秒中后在改变URL。
    $route的不足
        没法改变页面中多个地方的显示。只能改变ng-view所在的标签。没什么好的方法解决,只能凑活使用ng-include解决。
        没法递归使用:ng-view中没法再包含ng-view.

    最后导航怎么少得了超链接
        <a ng-href='#/admin/users/list'></a> 这是hashbang方式.
        如果在配置阶段使用
        .config(function($locationProvider){
                    $locationProvider.html5Mode(true);
                })
        打开了HTML5方式的URL模式,就使用
        <a ng-href='/admin/users/list'></a>

  • 相关阅读:
    TUN/TAP区别
    从日志文件解决ArcGIS Server性能低下问题的步骤(1)
    java异常
    Maven
    前车之鉴-web篇
    图论复习总结
    奇(qi)谋(ji)巧(yin)计(qiao)
    莫比乌斯反演呓语
    学习后缀数组笔记
    浅读叶青学长竞赛学习知识目录
  • 原文地址:https://www.cnblogs.com/formyjava/p/4166304.html
Copyright © 2011-2022 走看看