URL Routing

URL Routing

參考原文:https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views

Most states in your application will probably have a url associated with them. 

在你的應用程序中或多或少都會存在自定義狀態(states),他們可能有一個與之關聯的URL。

URL Routing was not an afterthought to the state mechanics, but was figured into the design from the beginning (all while keeping states separate from url routing)。

URL路由不是一個可有可無的狀態機制,從一開始url路由被指向設計好的路徑 (同時,來自URL路由的自定義狀態保持獨立)。

Here's how you set a basic url.

示例如下:

$stateProvider
    .state('contacts', {
        url: "/contacts",
        templateUrl: 'contacts.html'
    })

Now when the user accesses index.html/contacts then the 'contacts' state would become active and the main ui-view will be populated with the 'contacts.html' partial. 

當用戶訪問 index.html/contacts 的時候,'contacts' 狀態會起作用,指定的視圖將會被'contacts.html' 頁面內容填充。

Alternatively, if the user were to transition to the 'contacts' state via transitionTo('contacts') then the url would be updated to index.html/contacts

簡而言之,如果用戶想要過渡到'contacts' 狀態,URL就會更新到index.html/contacts。



URL Parameters

Basic Parameters

Often, URLs have dynamic parts to them which are called parameters.

通常,URLs的動態部分被稱爲狀態變數(parameters)。

There are several options for specifying parameters. 

這有幾個選項用於指定狀態變數(parameters

 A basic parameter looks like this:

一個簡單的狀態變數(parameters如下:

$stateProvider
    .state('contacts.detail', {
        url: "/contacts/:contactId",
        templateUrl: 'contacts.detail.html',        
        controller: function ($stateParams) {// If we got here from a url of /contacts/42
            expect($stateParams).toBe({contactId: "42"});
        }
    })

Alternatively you can also use curly brackets:

亦或用花括號:

// identical to previous example
url: "/contacts/{contactId}"

Examples:

示例:


  • '/hello/' - Matches only if the path is exactly '/hello/'. There is no special treatment for trailing slashes, and patterns have to match the entire path, not just a prefix.

'/hello/' - 只能匹配完全符合 '/hello/'的路徑。這裏的斜槓沒有特殊處理,這種模式只能匹配整個路徑,而不是僅僅作爲前綴來匹配。

  • '/user/:id' - Matches '/user/bob' or '/user/1234!!!' or even '/user/' but not '/user' or '/user/bob/details'. The second path segment will be captured as the parameter 'id'.

'/user/:id' 可以匹配'/user/bob' 或 '/user/1234!!!' 甚至 '/user/'也能匹配。但不能匹配'/user' 或 '/user/bob/details'。第二個路徑片段,作爲參數id被捕捉。

  • '/user/{id}' - Same as the previous example, but using curly brace syntax.

'/user/{id}'用法同上例,只是用了花括號語法。

  • '/user/{id:int}' - The param is interpreted as Integer.

'/user/{id:int}' - 參數會被轉化爲整數。

Note:

注意:


  • Parameter names may contain only word characters (latin letters, digits, and underscore) and must be unique within the pattern (across both path and search parameters).

狀態變parameters 的命名只能包含字符(拉丁字母,數字,下劃線)並且在該模式內必須確保唯一(該模式中的路徑和查詢狀態變parameters

Using Parameters in Links

To create a link that passes parameters, use the state name like a function and pass it an object with parameter names as keys. The proper href will be generated.

要創建傳遞狀態變parameters的鏈接,狀態名類似一個函數,傳入以狀態變parameters爲屬性的對象。這樣就能生成你想要的鏈接。

For example, using the above state which specified a contactId parameter, create a link like so:

例如,使用上文中的指定狀態變parameterscontactId 的狀態,生成一個鏈接如下:

<a ui-sref="contacts.detail({contactId: id})">View Contact</a>


The value for id can be anything in scope.

在規定範圍內id的值沒有限制。(譯者:文章中沒看到規定範圍的定義。猜測爲latin letters, digits, and underscore

Regex Parameters

A bonus to using curly brackets is the ability to set a Regular Expression rule for the parameter:

使用花括號語法的一個好處是能夠在狀態變量parameters)中使用正則表達式:

// will only match a contactId of one to eight number characters
url: "/contacts/{contactId:[0-9]{1,8}}"

Examples:

  • '/user/{id:[^/]*}' - Same as '/user/{id}' from the previous example.

  • 在上一個例子中,'/user/{id:[^/]*}' - 等同於 '/user/{id}' 

  • '/user/{id:[0-9a-fA-F]{1,8}}' - Similar to the previous example, but only matches if the id parameter consists of 1 to 8 hex digits.

  • '/user/{id:[0-9a-fA-F]{1,8}}' -幾乎與上例相同,除了只能匹配值爲1-8的16進制。

  • '/files/{path:.*}' - Matches any URL starting with '/files/' and captures the rest of the path into the parameter 'path'.

  • '/files/{path:.*}' -匹配所有以'/files/'開頭的路徑並且在狀態變量'path'中匹配剩餘部分。

  • '/files/*path' - Ditto. Special syntax for catch all.

  • '/files/*path' - 同上。匹配所有的特殊語法。

Warning:

  • Don't put capturing parentheses into your regex patterns, the UrlMatcher in ui-router adds those itself around the entire regex. You're effectively introducing a second capture group for the same parameter, which trips up the numbering in the child URL. You can use non-capturing groups though, i.e. (?:...) is fine.

  • 不要把捕捉括號放到正則表達式中,因爲ui-router中的鏈接匹配在整個正則表達式中自動添加捕捉括號。你有效的爲同一個狀態變量引入了第二個捕獲組,這個捕獲組挑出子URL的編號。當然你也可以用非捕獲組,也就是 (?:...)。

  • Regular expression can't include forward slashes as that's route segment delimiter

  • 正則表達式不能用斜槓作爲分隔符。

  • Route parameters with regular expressions can't be optional or greedy

  • 路由狀態變量爲正則表達式,正則表達式不能是可選的或貪婪匹配。

Query Parameters

You can also specify parameters as query parameters, following a '?':

你可以指定參數作爲查詢參數,尾部追加?即可

url: "/contacts?myParam"
// will match to url of "/contacts?myParam=value"

If you need to have more than one, separate them with an '&':

如果你需要一個以上的參數,用&分隔開:

url: "/contacts?myParam1&myParam2"
// will match to url of "/contacts?myParam1=value1&myParam2=wowcool"

Using Parameters without Specifying Them in State URLs

You still can specify what parameters to receive even though the parameters don't appear in the url. You need to add a new field params in the state and create links as specified in Using Parameters in Links

即使參數沒有出現在URL中你依然可以指定接收參數。你需要在state方法中新加領域參數並在指定使用參數的鏈接中創建鏈接。

For example, you have the state.

.state('contacts', {
        url: "/contacts",
        params: {
            param1: null
        },
        templateUrl: 'contacts.html'
    })

The link you create is

<a ui-sref="contacts({param1: value1})">View Contacts</a>

Or can you pass them to $state.go() too.

$state.go('contacts', {param1: value1})

URL Routing for Nested States

多狀態URL路由

Appended Routes (default)

附加路由(默認)

When using url routing together with nested states the default behavior is for child states to append their url to the urls of each of its parent states.

使用多狀態URL路由默認會在狀態的後面加入新的狀態。

$stateProvider
  .state('contacts', {
     url: '/contacts',     ...
  })
  .state('contacts.list', {
     url: '/list',     ...
  });

So the routes would become:

這樣一來路由變爲如下:

  • 'contacts' state matches "/contacts"

  • 'contacts' 狀態匹配 "/contacts"

  • 'contacts.list' state matches "/contacts/list". The urls were combined.

  • 'contacts.list' 狀態匹配 "/contacts/list". The urls were combined.鏈接組合起來了。

Absolute Routes (^)

絕對路由(^)

If you want to have absolute url matching, then you need to prefix your url string with a special symbol '^'.

如果你需要使用絕對鏈接匹配,那麼你需要加一個特殊前綴'^'。

$stateParams Service

As you saw previously the $stateParams service is an object that will have one key per url parameter. The $stateParams is a perfect way to provide your controllers or other services with the individual parts of the navigated url.

正如前文所見服務$stateParams是一個對象,它的每一個鏈接參數都會有一個值。$stateParams是分塊控制鏈接的好方法。

Note: $stateParams service must be specified as a state controller, and it will be scoped so only the relevant parameters defined in that state are available on the service object.

注意: 服務$stateParams 指定爲狀態控制器,他會有指定的控制範圍,所以只有定義在指定狀中的態參數才能起作用。

// If you had a url on your state of:
url: '/users/:id/details/{type}/{repeat:[0-9]+}?from&to'

// Then you navigated your browser to:
'/users/123/details//0'

// Your $stateParams object would be
{ id:'123', type:'', repeat:'0' }

// Then you navigated your browser to:
'/users/123/details/default/0?from=there&to=here'

// Your $stateParams object would be
{ id:'123', type:'default', repeat:'0', from:'there', to:'here' }

Important $stateParams Gotcha

$stateParams需要明白的細節

In state controllers, the $stateParams object will only contain the params that were registered with that state. So you will not see params registered on other states, including ancestors.

狀態控制器中 $stateParams 對象只包含註冊其中的參數。其他狀態中的參數不可見,即便是父狀態中的參數也不可見。

$stateProvider.state('contacts.detail', {
   url: '/contacts/:contactId',   
   controller: function($stateParams){      $stateParams.contactId  //*** Exists! ***//
   }
}).state('contacts.detail.subitem', {
   url: '/item/:itemId', 
   controller: function($stateParams){      $stateParams.contactId //*** Watch Out! DOESN'T EXIST!! ***//
      $stateParams.itemId //*** Exists! ***//  
   }
})
Instead, use a resolve statement in the parent route.
$stateProvider.state('contacts.detail', {
   url: '/contacts/:contactId',   
   controller: function($stateParams){      $stateParams.contactId  //*** Exists! ***//
   },
   resolve:{
      contactId: ['$stateParams', function($stateParams){          return $stateParams.contactId;
      }]
   }
}).state('contacts.detail.subitem', {
   url: '/item/:itemId', 
   controller: function($stateParams, contactId){
      contactId //*** Exists! ***//
      $stateParams.itemId //*** Exists! ***//  
   }
})

$urlRouterProvider

$urlRouterProvider has the responsibility of watching $location. When $location changes it runs through a list of rules one by one until a match is found. $urlRouterProvider is used behind the scenes anytime you specify a url in a state configuration. All urls are compiled into a UrlMatcher object (see $urlMatcherFactory below).

$urlRouterProvider會監測$location。當$location發生變化,$urlRouterProvider依據監測規則一個個的檢查直到匹配爲止。你任何時候在狀態配置中指定連接都會在幕後運轉$urlRouterProvider。所有連接將會編譯爲連接匹配對象($urlMatcherFactory 中將會介紹)。

There are several methods on $urlRouterProvider that make it useful to use directly in your module config.

這裏有很多關於$urlRouterProvider的使用技巧,這些技巧直接在模塊配置中使用堪稱利器。


when() for redirection

重定向-when() 

Parameters:

  • what String | RegExp | UrlMatcher The incoming path that you want to redirect.

  • handler String | Function The path you want to redirect your user to.

handler as String

If handler is a string, it is treated as a redirect, and is interpolated according to the syntax of match (i.e. like String.replace() for RegExp, or like a UrlMatcher pattern otherwise).

如果handler 是字符串,他將作爲重定向的路徑並依照匹配語法進行替換(例如:類似於 String.replace() ,類似於路徑匹配模式等等)。

app.config(function($urlRouterProvider){
    // when there is an empty route, redirect to /index   
    $urlRouterProvider.when('', '/index');
    // You can also use regex for the match parameter
    $urlRouterProvider.when(/aspx/i, '/index');
})

handler as Function

If the handler is a function, it is injectable. It gets invoked if $location matches. You have the option of inject the match object as $match

如果handler爲函數,它可注入其他服務。如果$location 匹配成功,調用函數。你可以注入諸如$match服務。

The handler can return:


  • falsy to indicate that the rule didn't match after all, then $urlRouter will continue trying to find another one that matches.

  • 返回錯誤的值表明未匹配成功,然後$urlRouter會繼續匹配其他對象。

  • String, which is treated as a redirect and passed to $location.url()

  • 返回的字符串做爲重定向路徑傳遞給$location.url()

  • nothing or any truthy value tells $urlRouter that the url was handled

  • 啥也沒有返回,或是返回正確的值,這等於告訴 $urlRouter鏈接已經被處理了。

Here's the actual code that we use to register state's that have urls behind the scenes.

$urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match, $stateParams) {    
if ($state.$current.navigable != state || !equalForKeys($match, $stateParams)) {
        $state.transitionTo(state, $match, false);
    }
}]);

otherwise() for invalid routes

無效路徑-otherwise() 

Parameters:

  • path String | Function The url path you want to redirect to or a function rule that returns the url path. The function version is passed two params: $injector and $location.

  • path String | Function 需要重定向的連接路徑或返回URL路徑的函數規則。函數傳遞兩個參數:$injector and $location

app.config(function($urlRouterProvider){
    // if the path doesn't match any of the urls you configured
    // otherwise will take care of routing the user to the specified url
    $urlRouterProvider.otherwise('/index');
    
    // Example of using function rule as param
    $urlRouterProvider.otherwise(function($injector, $location){
            ... some advanced code...
    });
})

rule() for custom url handling

自定義url handling-rule()

Parameters:

  • handler Function A function that takes in the $injector and $location services as arguments. You are responsible for returning a valid path as a string.

  • handler函數中傳入$injector 和 $location做爲參數,你需要返回可用路徑的字符串。

app.config(function ($urlRouterProvider) {
   // Here's an example of how you might allow case insensitive urls
   // Note that this is an example, and you may also use 
   // $urlMatcherFactory.caseInsensitive(true); for a similar result.
   $urlRouterProvider.rule(function ($injector, $location) {
        //what this function returns will be set as the $location.url
        var path = $location.path(), normalized = path.toLowerCase();
        if (path != normalized) {
            //instead of returning a new url string, I'll just change the $location.path directly so I don't have to worry about constructing a new url string and so a new state change is not triggered
            $location.replace().path(normalized);
        }
        // because we've returned nothing, no state change occurs
    });
})

$urlMatcherFactory and UrlMatchers

Defines the syntax for url patterns and parameter placeholders. This factory service is used behind the scenes by $urlRouterProvider to cache compiled UrlMatcher objects, instead of having to re-parse url patterns on every location change. Most users will not need to use $urlMatcherFactory directly, however it could be useful to craft a UrlMatcher object and pass it as the url to the state config.

給鏈接模式和參數佔位符定義了語法。這個服務工廠由$urlRouterProvider自動緩存編譯鏈接匹配對象,無需重新解析每個本地更改的鏈接模式。使用者無需直接使用 $urlMatcherFactory,它會精確匹配鏈接匹配對象並作爲鏈接傳入其中。

Please refer to the comment documentation within the $urlMatcherFactory file to learn more.

學習更多相關知識請參考$urlMatcherFactory file

var urlMatcher = $urlMatcherFactory.compile("/home/:id?param1");
$stateProvider.state('myState', {
    url: urlMatcher 
});


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章