翻译:深入 AngularUI Router

原文地址:http://www.ng-newsletter.com/posts/angular-ui-router.html

ui-router 是 AngularUI 库提供的特别有用的一个部分,是一个通过提供状态机机制,而不是简单的 URL 来组织我们的界面的路由框架。

这个库提供了针对视图的众多的额外控制,我们可以创建嵌套的视图,在单个页面使用多个视图,多个视图来控制单个视图,还有更多特性。对于更加精细的控制和更为复杂的应用,ui-router 是非常棒的工具。

Installation

安装 ui-router,既可以直接下载发布版本,也可以通过 bower 来获取。

$ bower install angular-ui-router --save

然后,需要在页面中进入这个库,当然要先加载 angular 库。

<script type="text/javascript" src="angular-ui-router.js"></script>

在 angular 中注入 ui.router.

angular.module(‘myApp‘, [‘ui.router‘])

不像 angular 内置的 ngRoute, ui-router 可以嵌套视图,它是基于状态,而不 URL 的。

也不像 ngRoute 使用 ng-view 指令,在 ui-router 中,我们使用 ui-view 指令。

当在 ui-router 中考虑路由和状态的关系时,我们主要关注应用的什么状态对应应用的什么路由。

<div ng-controller="DemoController">
  <div ui-view></div>
</div>

类似 ngRoute, 对于给定的状态,模板中的内容将会填充到 <div ui-view></div> 元素,每个模板还可以包含自己的 ui-view ,这就是我们可以支持嵌套路径的原因。

定义路径的时候,我们使用 .config 方法,像通常一样,但是使用 $stateProvider 来替换 $routeProvider。

.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state(‘start‘, {
      url: ‘/start‘,
      templateUrl: ‘partials/start.html‘
    })
});

这样,我们;定义了名为 start 的状态,传递的对象定义了状态配置信息,或者称为 stateConfig,类似于路由配置对象,我们通过它配置状态信息。

template, templateUrl, templateProvider

可以使用下面三种之一的方式来定义视图使用的模板:

  • template, 字符串方式的模板内容,或者是一个返回 HTML 的函数
  • templateUrl, 模板的路径,或者返回模板路径的函数
  • templateProvider, 返回 HTML 内容的函数

例如

$stateProvider.state(‘home‘, {
  template: ‘<h1>Hello {{ name }}</h1>‘
});

Controller

类似于 ngRoute,我们既可以通过控制器的名字来关联一个预定义的控制器,也可以直接创建一个控制器函数来处理。

如果没有对应的模板定义,控制器对象就不会被创建。

Resolve

使用 resolve 功能,我们可以准备一组用来注入到控制器中的依赖对象。在 ngRoute 中,resolve 可以在路由实际渲染之前解决掉 promise

resolve 选项提供一个对象,对象中的 key 就是准备注入 controller 的依赖名称,值则是创建对象的工厂。

如果是一个串,就试图用这个串来匹配当前已经注册的服务名称,如果是一个函数,执行这个函数,返回的值就是依赖。如果函数返回一个 promise,在控制器被实例化之前,将会被 resolved,返回的值被注入到 controller 中。

$stateProvider.state(‘home‘, {
  resolve: {
    // This will return immediately as the
    // result is not a promise
    person: function() {
      return {
        name: "Ari",
        email: "[email protected]"
      }
    },
    // This function returns a promise, therefore
    // it will be resolved before the controller
    // is instantiated
    currentDetails: function($http) {
      return $http({
        method: ‘JSONP‘,
        url: ‘/current_details‘
      });
    },
    // We can use the resulting promise in another
    // resolution
    facebookId: function($http, currentDetails) {
      $http({
        method: ‘GET‘,
        url: ‘http://facebook.com/api/current_user‘,
        params: {
          email: currentDetails.data.emails[0]
        }
      })
    }
  },
  controller: function($scope, person,
                currentDetails, facebookId) {
      $scope.person = person;
  }
})

URL

url 用来设置应用对应的一个特定状态. 也就是说,我们可以通过状态栏获得深度链接相同的特性,而不是使用简单的 url。

这个特性类似于 ngRoute 中的 URL, 但是,可以被看作一个重大的升级,后面我们就会看到。

简单的路由类似下面所示。

$stateProvider
  .state(‘inbox‘, {
    url: ‘/inbox‘,
    template: ‘<h1>Welcome to your inbox</h1>‘
  });

当我们导航到 /index 的时候,应用将会过渡到 inbox 状态,使用这里提供的内容模板填充 ui-view 的内容。

URL 中可以包含多种内容,令人难以置信的强大,可以像在 ngRoute 中设置简单的参数。

$stateProvider
  .state(‘inbox‘, {
    url: ‘/inbox/:inboxId‘,
    template: ‘<h1>Welcome to your inbox</h1>‘,
    controller: function($scope, $stateParams) {
      $scope.inboxId = $stateParams.inboxId;
    }
  });

这里,我们创建了 :inboxId 参数来捕获 url 中的第二部分,例如,如果应用访问 /inbox/1,那么,$stateParameter.inboxId 就成为 1, 实际上, $stateParams 的值将为 { inboxId: 1 }

也可以使用另外一种语法。

url: ‘/inbox/{inboxId}‘

路径必须完全匹配,不像 ngRoute, 如果用户访问 /inbox/,这个路径配置将会工作,但是,如果访问 /inbox,这个状态就不会被激活。

还可以使用正则表达式来表示参数,这样可以通过正则表达式来设置匹配规则,例如。

// Match only inbox ids that contain
// 6 hexidecimal digits
url: ‘/inbox/{inboxId:[0-9a-fA-F]{6}}‘,
// Or
// match every url at the end of `/inbox`
// to `inboxId` (a catch-all)
url: ‘/inbox/{inboxId:.*}‘

注意,不能在路由中使用捕获组

甚至可以在路径中使用查询参数。

// will match a route such as
// /inbox?sort=ascending
url: ‘/inbox?sort‘

嵌套路由

我们可以使用 url 参数添加到路由中来实现嵌套路由。这样可以提供多个 ui-views 在我们的页面中,例如,我们可以在 /inbox 之上,提供嵌套的独立路由。

$stateProvider
  .state(‘inbox‘, {
    url: ‘/inbox/:inboxId‘,
    template: ‘<div><h1>Welcome to your inbox</h1>            <a ui-sref="inbox.priority">Show priority</a>            <div ui-view></div>            </div>‘,
    controller: function($scope, $stateParams) {
      $scope.inboxId = $stateParams.inboxId;
    }
  })
  .state(‘inbox.priority‘, {
    url: ‘/priority‘,
    template: ‘<h2>Your priority inbox</h2>‘
  });

第一个路由与前面一样,现在还有第二个路由,一个匹配 inbox 之下的子路由,语法 (.) 表示这是一个子路由。

/inbox/1 匹配第一个状态,/inbox/1/priority 则匹配第二个状态。使用这种语法,我们可以在父路由中支持嵌套的 url。在父视图中的 ui-view 指令将会处理 priority。

Params

params 选项是参数名称或者正则的数组。它不能合并 url 选项,当状态激活的时候,应用会使用这些参数填充 $stateParams 服务。

Views

我们可以在 state 中提供命名的视图。这是强大的特性,在单个视图中,我们可以定义多个视图,甚至使用单个模板。

如果我们使用了 views 参数,那么,templateUrl, template 和 templateProvider 就会忽略。如果我们希望包含父模板,我们需要创建一个抽象模板。

假如我们有如下模板。

<div>
  <div ui-view="filters"></div>
  <div ui-view="mailbox"></div>
  <div ui-view="priority"></div>
</div>

我们可以创建命名的视图,然后填充对应的模板。每个子视图都可以有特有的模板,控制器和数据。

$stateProvider
  .state(‘inbox‘, {
    views: {
      ‘filters‘: {
        template: ‘<h4>Filter inbox</h4>‘,
        controller: function($scope) {}
      },
      ‘mailbox‘: {
        templateUrl: ‘partials/mailbox.html‘
      },
      ‘priority‘: {
        template: ‘<h4>Priority inbox</h4>‘,
        resolve: {
          facebook: function() {
            return FB.messages();
          }
        }
      }
    }
  });

在这个例子中,我们有两个命名的视图嵌套在抽象视图中。

Abstract

我们永远不能直接激活抽象模板,但是,可以通过派生模板来激活。

抽象模板提供封装命名视图的模板,可以传递 $scope 对象给派生子模板。可以通过它解决依赖问题,或者特定数据处理,或者简单地同样的 url 来嵌套多个路由,例如,所有路由都在 /admin 下面。

$stateProvider
  .state(‘admin‘, {
    abstract: true,
    url: ‘/admin‘,
    template: ‘<div ui-view></div>‘
  })
  .state(‘admin.index‘, {
    url: ‘/index‘,
    template: ‘<h3>Admin index</h3>‘
  })
  .state(‘admin.users‘, {
    url: ‘/users‘,
    template: ‘<ul>...</ul>‘
  });

onEnter, onExit

在应用进入或者退出视图的时候,会调用这些回调函数。它们都可以设置回调函数;函数可以访问获取的数据。

这些回调函数可以提供我们一些能力,在访问新视图,或者改变当前状态的时候。这里是很好的执行 "Are you sure?" 对话框,或者请求用户在进入之前登陆的地方。

Data

我们可以附加任意的数到我们的状态配置对象 configObject 上,data 属性类似于 resolve 属性,除了不会注入到控制器,也不会 resolve promise。

当需要从父状态向子状态传递数据的时候,附加数据是方便的途径。

Evnets

类似 ngRoute 服务,angular-route 服务在状态生命周期的不同时间点会触发多种事件。我们可以通过在 $scope 中监听来处理这些事件。

所有的下面的事件都会在 $rootScope 中触发,所以,我们可以在任何 $scope 对象中监听这些事件。

State change events

可以如下监听

$scope.$on(‘$stateChangeStart‘,
function(evt, toState, toParams, fromState, fromParams), {
  // We can prevent this state from completing
  evt.preventDefault();
});

$stateChangeStart

当从一个状态开始向另外一个状态过度的时候触发。

$stateChangeSuccess

当状态过渡完成之后触发。

$stateChangeError

在状态过渡中出现错误。常见的错误例如,不能获取模板,或者 promise 不能成功 resolve 等等

视图加载事件

ui-router 也提供了视图加载阶段的事件。

$viewContentLoading

视图开始加载,但是,在 DOM 渲染之前。

可以如下监听。

$scope.$on(‘$viewContentLoading‘,
function(event, viewConfig){
    // Access to all the view config properties.
    // and one special property ‘targetView‘
    // viewConfig.targetView
});

$viewContentLoad

视图已经加载,渲染完成。

$stateParams

在前面的内容中,我们使用 $stateParams 来从 url 参数中获取 params ,这个服务,与 url 不同。

例如,如果我们 inbox 状态的 url 如下。

url: ‘/inbox/:inboxId/messages/{sorted}?from&to‘

用户使用下面的 url 访问

/inbox/123/messages/ascending?from=10&to=20

我们的 $stateParams 对象将获取如下数据。

{inboxId: ‘123‘, sorted: ‘ascending‘, from: 10, to: 20}

$urlRouterProvider

类似 ngRoute, 可以创建当特定的 url 访问时处理的规则。

可以通过不同的 url 激活不同的状态,所以在管理激活和加载状态的时候, $urlRouterProvider 并不是必须的。在状态管理之外的时候才会需要,比如重定向,或者验证的时候。

when()

when 函数需要两个参数,我们希望匹配的路径,另外就是我们希望重新定向的目标。也可以是一个函数。

例如,如果希望任何空的路由到我们的 /inbox 路由中。

.config(function($urlRouterProvider) {
  $urlRouterProvider.when(‘‘, ‘/inbox‘);
});

如果提供一个函数处理,路由匹配的时候,这个函数就会被调用,它可以返回下列三种之一的结果。

  • false,这个回应告诉 $urlRouter 规则并不匹配,应该查找其它匹配的状态,在我们希望验证用户是否访问正确地址的时候很有用。
  • 字符串,$urlRouter 将其作为重定向目标。
  • true 或者 undefined,函数已经处理了这个 url

otherwise()

与 ngRoute 中的 oterwise() 方法类似,oterwiese() 在没有其它路由匹配的情况下重定向。这是创建默认 url 的好方法。

otherwise() 函数只需要一个参数,一个字符串或者一个函数。

如果提供了一个字符串,就会被看做一个默认地址,在任何错误的或者不能匹配任何路由的时候,就会被重定向到这个地址。

如果是一个函数,在没有其它路由匹配的时候,就会被执行

.config(function($urlRouterProvider) {
  $urlRouterProvider.otherwise(‘/‘);
  // or
  $urlRouterProvider.otherwise(
    function($injector, $location) {
      $location.path(‘/‘);
    });
});

rule()

如果我们希望处理任何路由,或者在其它路由之前进行一些处理,可以使用 rule() 函数。

我们必须返回一个验证的路径串

app.config(function($urlRouterProvider){
  $urlRouterProvider.rule(
    function($injector, $location) {
      return ‘/index‘;
    });
})

创建报名向导

为什么不使用一下它呢?

我们创建一个报名的向导来演练一下 ui-router 的使用。

使用 ui-router ,我们创建一个简单的报名服务,使用一个控制器来处理报名。

首先,我们创建应用的视图。

<div ng-controller="WizardSignupController">
  <h2>Signup wizard</h2>
  <div ui-view></div>
</div>

在这个视图中,我们定义了报名视图。下一步,在报名向导中,需要三步

  • start,在这一步,我们获取用户名称,提供欢迎信息
  • email, 这里,我们获取用户的 email 信息
  • finish, 这里,用户完成报名,我们简单地显示完成页面

报名处理依赖 wizardapp.controllers 模块,

angular.module(‘wizardApp‘, [
  ‘ui.router‘,
  ‘wizardapp.controllers‘
  ]);

我们的 wizardSignupController 控制器,使用 $scope.user 对象在整个过程中收集信息。

angular.module(‘wizardapp.controllers‘, [])
.controller(‘WizardSignupController‘,
  [‘$scope‘, ‘$state‘, function($scope, $state) {
    $scope.user = {};
    $scope.signup = function() {}
}]);

现在,向导处理逻辑处理主要工作,配置 config()

angular.module(‘wizardApp‘, [
  ‘ui.router‘, ‘wizardapp.controllers‘
  ])
.config([‘$stateProvider‘, ‘$urlRouterProvider‘,
function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state(‘start‘, {
      url: ‘/step_1‘,
      templateUrl: ‘partials/wizard/step_1.html‘
    })
    .state(‘email‘, {
      url: ‘/step_2‘,
      templateUrl: ‘partials/wizard/step_2.html‘
    })
    .state(‘finish‘, {
      url: ‘/finish‘,
      templateUrl: ‘partials/wizard/step_3.html‘
    });
}]);

这样,我们基本的流程就已经有了。现在,如果用户导航到 /step_1,就会看到开始页面,尽管现在地址是 /step_1, 而我们希望是 /wizard/step_1

为了这个效果,我们创建 abstract 状态来寄宿各个步骤。

.config([‘$stateProvider‘, ‘$urlRouterProvider‘,
function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state(‘wizard‘, {
      abstract: true,
      url: ‘/wizard‘,
      template: ‘<div><div ui-view></div></div>‘
    })
    .state(‘wizard.start‘, {
      url: ‘/step_1‘,
      templateUrl: ‘partials/wizard/step_1.html‘
    })
    .state(‘wizard.email‘, {
      url: ‘/step_2‘,
      templateUrl: ‘partials/wizard/step_2.html‘
    })
    .state(‘wizard.finish‘, {
      url: ‘/finish‘,
      templateUrl: ‘partials/wizard/step_3.html‘
    });
}]);

这样,它们都安全地嵌套到 /wizard 之下了。

在状态之间进行导航,我们使用 ui-router 提供的指令 ui-sref 来生成链接,这个指令用来生成导航链接。

例如,step_1.html 如下。

<!-- step_1.html -->
<h3>Step 1</h3>
<form ng-submit="">
  <input type="text" ng-model="user.name" placeholder="Your name" />
  <input type="submit" class="button" value="Next" ui-sref="wizard.email"/>
</form>

我们还希望在报名流程完成之后,执行特定的动作,来调用定义在父控制器上的 signup 函数,我们可以在最后的步骤中添加一个控制器来调用 $scope.signup() 函数。由于整个向导封装在 WizardSignupControoler 中,我们可以像通常一样访问嵌套的 scope 对象。

.state(‘wizard.finish‘, {
  url: ‘/finish‘,
  templateUrl: ‘partials/wizard/step_3.html‘,
  controller: function($scope) {
    $scope.signup();
  }
});

总结

在这里,我们深入讨论了 ui-router 几乎全部的特性,我们发现这个库非常有用,希望也能帮到你。

时间: 2024-10-13 02:36:16

翻译:深入 AngularUI Router的相关文章

深入 AngularUI Router

翻译:深入 AngularUI Router 原文地址:http://www.ng-newsletter.com/posts/angular-ui-router.html ui-router: https://angular-ui.github.io/ui-router/site/#/api/ui.router ui-router 是 AngularUI 库提供的特别有用的一个部分,是一个通过提供状态机机制,而不是简单的 URL 来组织我们的界面的路由框架. 这个库提供了针对视图的众多的额外控制

AngularUI Router 概要【转】

通过AngularJS来创建SPA(single page application),要想让页面导航看起来跟一般Web页面一样的话,路由相当重要.AngularUI Router是AngularUI 团队开发的一个AngularJS路由模块,相比AngularJS的标准路由ngRoute,它更灵活,基于state而不是URL在一个页面中加载多个View并保持View的层次,Nested States & Views以及Multiple & Named Views.UI-Router被认为是

angular ui-router

翻译:深入 AngularUI Router 原文地址:http://www.ng-newsletter.com/posts/angular-ui-router.html ui-router: https://angular-ui.github.io/ui-router/site/#/api/ui.router ui-router 是 AngularUI 库提供的特别有用的一个部分,是一个通过提供状态机机制,而不是简单的 URL 来组织我们的界面的路由框架. 这个库提供了针对视图的众多的额外控制

AngularJS路由系列(6)-- UI-Router的嵌套State

本系列探寻AngularJS的路由机制,在WebStorm下开发.本篇主要涉及UI-Route的嵌套State. 假设一个主视图上有两个部分视图,部分视图1和部分视图2,主视图对应着一个state,两个部分视图分别对应state1和state2,那state与state1和state2形成了嵌套关系. AngularJS路由系列包括: 1.AngularJS路由系列(1)--基本路由配置2.AngularJS路由系列(2)--刷新.查看路由,路由事件和URL格式,获取路由参数,路由的Resolv

Ionic 项目创建

1. Ionic介绍 Ionci 是一个强大的HTML5 应用程序框架. 可以帮助您使用Web技术,如HTML, CSS和Javascript构建原生体验的移动应用程序. Ionic主要关注外观和体验,以及和你的应用程序UI交互,特别适合基于Hybirrd模式的HTML5移动程序开发. Ionic是一个轻量级手机UI库,具有速度快,界面现代化,美观等特点,为了解决其他一些UI库在手机上运行缓慢的问题. 2. Angularjs介绍 Ionic整合了AngularJs integrate Ioni

ionic默认样式android和ios差异

ionicframework中android和ios在默认样式上有一些不同的地方,官方文档中都有说明,但是经常会想不起. 一.差异: 1.tab位置,$ionicConfigProvider, tabs.position(value) Android 默认是顶部(top),Ios是底部 (bottom) 2.标题android默认靠左边,ios默认居中 navBar.alignTitle(value) 二:解决方案: 1.将Android的tab默认设置是底部显示: 修改app.js文件如下:

Backbone与Angular的比较

Backbone与Angular的比较 作者 Victor Savkin ,译者 邵思华 发布于 2014年1月17日 | 注意:QCon全球软件开发大会(北京)2016年4月21-23日,了解更多详情!4 讨论 分享到:微博微信FacebookTwitter有道云笔记邮件分享 稍后阅读 我的阅读清单 将不同的思想和工具进行对比,是一种更好地理解它们的方式.在本文中,我首先将列举在创建web应用程序时需要重复进行的各项任务,随后为你展现Backbone和Angular将如何帮助你完成这些工作.

angular UI-Router 示例二

基于第一个示例,我们再深入学习一下稍微复杂点的东西. 一.要实现的效果如下所示: index.html about.html 可以看出,我们需要使用路由来切换到不同的视图.ui-router提供了让我们可以做路由嵌套和视图命名的特性,在接下来的示例中我们将逐一分析. 二.代码实现部分 我们需要一个显示模板作为页面显示的容器,因此新建index.html <!DOCTYPE html> <html> <head> <link href="css/boots

篇章一:[AngularJS] 使用AngularAMD動態載入Controller

前言 使用AngularJS來開發Single Page Application(SPA)的時候,可以選用AngularUI Router來提供頁面內容切換的功能.但是在UI Router的使用情景裡,需要開發人員將每個State所使用的Controller預先載入之後,才能正常的切換頁面內容.這也就代表開發人員所建立的SPA,必須要在啟動的當下,就先將整個SPA所用到的Controller都預先載入到瀏覽器之中.而這樣的預先載入所有Controller備用的動作,在大型的專案中很容易造成瀏覽器