AngularJS開發指南14:AngularJS的服務詳解


服務是一種由服務器端帶到客戶端的特性,它由來已久。AngularJS應用中的服務是一些用依賴注入捆綁在一起的可替換的對象。服務是最常和依賴注入一起用的,它也是AngularJS中的關鍵特性。

接下來,我們詳細講解下$location服務。

$location服務,解析地址欄中的URL(基於window.location),讓你在應用代碼中能獲取到。改變地址欄中的URL會反應到$location服務中,反之亦然。

$location服務:

  • 暴露當前地址欄的URL,這樣你就能
    • 獲取並監聽URL。
    • 改變URL。
  • 當出現以下情況時同步URL
    • 改變地址欄
    • 點擊了后退按鈕(或者點擊了歷史鏈接)
    • 點擊了一個鏈接
  • 一系列方法來獲取URL對象的具體內容用(protocol, host, port, path, search, hash)

window.location和$location.service的區別:

  window.location $location.service
目的 允許對當前瀏覽器位置的讀寫 同左
API 暴露一個能被讀寫的對象 暴露jquery風格的讀寫器
是否在AngularJS應用生命周期中和應用整合 在應用聲明周期內的每一個階段可獲取到,並且和$watch整合
是否和HTML5 API的無縫整合 是(對低級瀏覽器優雅降級)
和應用的上下文是否相關 否,window.location.path返回"/docroot/actual/path" 是,$location.path()返回"/actual/path"

什么時候該用$location

在你想對URL的改變做出響應時,或者在你想改變當前URL時。

它不能用來干什么

在URL改變時,不能刷新整個頁面。一定要的話,用低級的API,$window.location.href

$location服務的具體行為取決於它初始化時的配置。默認設置對大多數應用都是適合的,你也可以自定義配置來增加些新特性。

$location服務初始化好以后,你就可以使用jquery風格的讀寫器和它交互了,你可以獲取或者改變當前URL。

要配置$location服務,檢索$locationProvider並把參數設置成以下這樣:

    • html5Mode(模式): {boolean}
      true - 參閱HTML5模式
      false - 參閱Hashbang模式
      default: false

    • hashPrefix(前綴): {string}
      Hashbang URLs的前綴 (在Hashbang模式中或者低級瀏覽器中使用)
      default: '!'

配置示例

$locationProvider.html5Mode(true).hashPrefix('!');

讀寫器(getter and setter)

$location服務為URL只讀部分(absUrl, protocol, host, port)提供讀方法,為可讀寫部分(url, path, search, hash)提供讀寫方法。

所有的寫方法返回同一個$location對象來支持鏈式操作。

$location服務有一個特殊的replace方法可以用來告訴$lacation服務下一次自動和瀏覽器同步,上一條瀏覽記錄應該被替換而不是創建一個新的。這在重定向的時候很好用。不這樣的話容易使后退按鈕失效(點后退時會又觸發重定向)。要改變URL而不添加新的歷史記錄,你可以這樣做:

$location.path('/someNewPath');
$location.replace();
// or you can chain these as: $location.path('/someNewPath').replace();

注意:寫方法並不會馬上更新window.location,而是在作用域的$digest階段將多個$location操作合並成一個對windiow.location對象的commit操作。因為多個操作之后對瀏覽器來說都會只是一個,所以只要調用一次replace()方法就能實現瀏覽器記錄的替換操作。一旦瀏覽器更新了,$location服務就會將replace方法的標志重置,以后的改變就會創建新的歷史記錄,直到再次調用replace方法。

你可以給$location服務傳遞特殊字符,它會根據RFC 3986規則來編碼。當你調用寫方法時:

  • 所有傳遞給寫方法(如path(), search(), hash())的值都會被編碼。
  • 讀方法(path(), search(), hash()不帶參數的調用)返回解碼后的值。
  • 當你調用absUrl()時,會返回各部分經過了編碼的完整url。
  • 當你調用url()時,返回的值是path, search 和hash,形式是/path?search=a&b=c#hash

$location服務有兩種用來控制地址欄URL格式的配置:Hashbang模式(默認)和HTML5模式(使用HTML5歷史API)。應用會使用兩種模式中相同的API,並且$location服務會使用需要的URL片段和瀏覽器API來幫助改變URL或者進行歷史管理。

它們兩者的區別:

               Hashbang模式               HTML5模式
配置:               默認                   { html5Mode: true }
URL格式:             所有瀏覽器都支持hashbang URLs      在高級瀏覽器中使用regular URLs,低級瀏覽器使用hashbang URLs
<a href=""> 鏈接重寫:      否                     是
需要服務器端配置:         否                    是

Hashbang模式(默認mode)

使用這個模式的話,$location會在所有瀏覽器中使用Hashbang URLs。

支持網絡爬蟲

你需要添加特別的meta標記在你的文檔的頭部才能支持對你的AJAX應用的索引。

<meta name="fragment" content="!" />

這能讓網絡爬蟲,請求帶有_escaped_fragment_形式的參數鏈接,這樣你就能識別爬蟲並且返回一個HTML的快照了。

HTML5模式

在HTML5模式中,$location服務的讀寫器和瀏覽器的URL地址通過HTML5歷史API交互,這使你能用regular URL path搜索各組成部分,和hashbang是等效的。 

  • 在低級瀏覽器中使用了regular URL -> 重定向成hashbang URL
  • 在現代瀏覽器中打開了一個hashbang URL -> 重寫成regular URL

低級瀏覽器使用的降級

在支持HTML5 歷史 API的瀏覽器中,$location服務的讀寫器和瀏覽器的URL地址通過HTML5歷史API交互。 如果瀏覽器不支持HTML5 歷史API, $location服務會自動降級成使用hashbang URLs。你就不用擔心瀏覽器的支持性了。$location服務總是會用最好的選擇。

Html鏈接重寫

當你使用歷史API模式時,在不同的瀏覽器中你需要使用不同的鏈接,但是你需要做的僅僅是指定好regular URL形式的鏈接,如 <a href="/some?foo=bar">link</a>

當用戶點擊這個鏈接時

  • 在低級瀏覽器中,URL轉換成/index.html#!/some?foo=bar
  • 在現代瀏覽器中轉換成/some?foo=bar

如果是下面的這幾種形式,鏈接不會被重寫。取而代之的是,瀏覽器會根據鏈接重新加載頁面。

  • 包含target的鏈接
    Example: <a href="/ext/link?a=b" target="_self">link</a>

  • 指向其他域的絕對路徑 Example: <a href="http://angularjs.org/">link</a>

  • 當base被定義時,使用'/'開頭指向一個不同的base路徑。 Example: <a href="/not-my-base/link">link</a>

相對鏈接

記住要檢查所有的相對連接、圖片、腳本等。你必須指定你主頁面的base url(<base href="/my-base">),或者你使用絕對路徑也行,因為相對路徑會結合文檔的初始絕對路徑轉換成絕對路徑。文檔初始路徑通常和應用的根路徑不一樣。

我們強烈推薦應用使用文檔根節點開始的歷史API,因為它能處理好所有相對路徑的問題。

不同瀏覽器中的鏈接

因為HTML模式的重寫能力,你的用戶能在低級瀏覽器中使用regualr url,在現代瀏覽器中使用hashbang url。

  • 在高級瀏覽器中會將hashbang URLs重寫成regular URLs。
  • 在低級瀏覽器中使用了regular URL會被重定向成hashbang URL。

注意

頁面的重新加載

$location服務只能讓你改變URL;不能讓你重新加載頁面。當你需要重新加載頁面或者跳轉到另外的頁面時,請使用更低級別的API,$window.location.href。

在作用域生命周期外使用$location

$location知道應用作用域的聲明周期。當URL改變時,它會更新$location,並且調用$apply,這樣所有監聽它的程序都會收到。當你在$digest階段時改變URL。$location將改變傳遞給瀏覽器,並且通知所有的監聽者。但是如果在應用之外使用$location的話(比如,在DOM事件中或者測試中),你就要手動調用它的$apply方法來傳遞改變了。

$location.path() 和 "!" "/" 前綴

一個路徑應該總是以斜杠開始;$location.path()寫方法會在沒有前綴"/"時自動添加。

注意,hashbang模式中的"!"前綴實際上不是$location.path()的一部分,它其實是hashPrefix。

$location的雙向綁定

AngularJS的編譯器目前不支持對$location對象的雙向綁定。如果你需要對$location對象(在input元素上使用ngModel指令)進行雙向綁定,你需要指定一個帶有兩個監聽者的額外的模型屬性(比如locationPath),這兩個監聽者各負責一個方向。

<!-- html -->
<input type="text" ng-model="locationPath" />
// js - controller $scope.$watch('locationPath', function(path) { $location.path(path); }); $scope.$watch('$location.path()', function(path) { scope.locationPath = path; });

 

 

 

 

加油!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM