規劃 index.html 足夠載入其他 html 的空間
為了要將其他 html 併入最主要的 html, 首要是需要規劃一個 div 之類的空間,可以給 angular-router 去做不刷新頁面的載入。
<html> <head> <title>Hallo, angular</title> </head> <body> <div id="container" ui-view=""> </div> </body> </html>請注意上方在 div 中的 "ui-view" ,這是屬於 ui-router 載入其他 html 文件到這個 div 的識別標籤。
Angular 的路由器網址格式
angular 的網址格式,是在 html 文件,或是倒斜線後面加一個 # 號作為連結,在 # 號後面的路徑就是 angular 應用程式識別的路徑,舉個例子:xxx.com/index.html/#/this/is/router
又或是
xxx.com/#/this/is/router
而我們在建置非刷新格式的功能時,就需要定義 # 號後面的路徑。
UI-Router, Angular Router
在這邊,你需要知道 angular-router 是採用傳統的 "/hallo/test" 來載入,而 ui-router 是採用 state 的方式載入,網址寫起來會像這樣 :“ hallo.test ”
用來取代
/hallo/test
但是,你在建置時也必須先建置 hallo 的路由,才可以建置 hallo 底下的子路由 hallo.test。
理解一下這段代碼,你就會知道:
var test = angular.module('apostle',['ngRoute','oc.lazyLoad','ui.router','pascalprecht.translate','ngFileUpload']); test.config(function($stateProvider,$urlRouterProvider,$routeProvider,$translateProvider,$ocLazyLoadProvider){ $urlRouterProvider.otherwise('http://google.com/?q=88888888'); //如果發現沒有在清單內的路由,就導向 $stateProvider.state('index',{ url:'/', template:'<h1>Nothing can be loaded!</h1>', redirectTo: 'account.user' }) .state('account',{ url:'/account', template:'<div id="container" ui-view></div>', redirectTo:"account.user" }) .state('account.user',{ url:'/user', templateUrl:"./pages/account/user.html", controller:'userSettingsController', resolve: { loadMyCtrl: ['$ocLazyLoad', function($ocLazyLoad) { loadScript("./js/plugin/Croppie/croppie.js"); loadScript("./js/plugin/intl-tel-input/build/js/intlTelInput.min.js"); return $ocLazyLoad.load({ name: 'userSettingsController', files: ['./js/controllers/account/user.js'] }); }] } }); //注意一下這個區塊,等等是用來介紹建置 $translate 多國語言功能放置的區塊 // // })看到上面的每一個 state ,這個就是 ui-router 吃的路由方式,而這些 state 中的 url,就是指定名稱的路徑,換句話說,如果 test.aa 不想為 "/test/aa" ,你也可以把 url 改成其他的,像是 "/bye" ,那麼只要使用導向狀態 test.aa ,就會跳轉到 "/test/bye"。
最簡單看到導向狀態的方式,就是在 index.html 的選單中,把 <a href> 的連結,改成 <a ui-sref="test.aa"> ,這麼一來,這個 ui-router 就會自動找到 state 的狀態路徑。
然而,你發現第二個 state ,為何要在 template 加上一層原本在 body 就有的命名都一樣的 div 呢?
template 本身就可以直接顯示 html ,或是你可以用 templateUrl 來載入其他路徑的 html 。
template 執行後,將會複寫當初擁有 ui-view 識別字的 <div id="container" ui-view> ,這會讓子路由沒有參考的 <div id="container" ui-view> (最主要是識別字 ui-view 已經被覆寫了) ,因為這一段已經被覆寫,所以訪問子路由只會是空白,因此我們只能把子路由前一段當作過度點,也許是分類方便的關係吧,加上 template 後, 再導向到主功能去。
LoadScript, ocLazyLoad
從上方的 js 程式碼中, loadScript 帶有 js 路徑的參數,這段是我寫的後載入 js 強化版 (? 。請加在你的 router 文件之前。
function loadScript(url){ var resource = document.createElement('script'); resource.src = url; var script = document.getElementsByTagName('script')[0]; script.parentNode.insertBefore(resource, script); }這麼一來只要需要做後載入 js 來源文件,就可以用到。
ocLazyLoad 可以輔助 ui-router 後載入 controller 的問題
因此先下載 ocLazyLoad ,可以參考上方的做法,先找到你的 controller 的 js 文件,寫一段範例:
angular.module('test').controller('userSettingsController',function($scope,$translate){ console.log("Loaded page and controller: userSettingsController"); });之所以要寫 angular.module('test').controller ,是因為我發現寫 test.controller() 都沒反應,所以只能這樣寫,或許論壇上有更好的解法!
Rest API , Postfix, Header 在 Post 正確傳輸方法
postfix 這個模組解決了 angular 在 post 上的一些問題,當你在 java 後端接收不到 post 資料時,不妨可以先下載,或是使用這段 code 加入在 $http.post 前面:$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8'; /** * The workhorse; converts an object to x-www-form-urlencoded serialization. * @param {Object} obj * @return {String} */ var param = function(obj) { var query = '', name, value, fullSubName, subName, subValue, innerObj, i; for(name in obj) { value = obj[name]; if(value instanceof Array) { for(i=0; i<value.length; ++i) { subValue = value[i]; fullSubName = name + '[' + i + ']'; innerObj = {}; innerObj[fullSubName] = subValue; query += param(innerObj) + '&'; } } else if(value instanceof Object) { for(subName in value) { subValue = value[subName]; fullSubName = name + '[' + subName + ']'; innerObj = {}; innerObj[fullSubName] = subValue; query += param(innerObj) + '&'; } } else if(value !== undefined && value !== null) query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&'; } return query.length ? query.substr(0, query.length - 1) : query; }; // Override $http service's default transformRequest $http.defaults.transformRequest = [function(data) { return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data; }];
如果你有使用 postfix ,但是還是發現後段收不到 post 方法的資料,你可以這樣做:
var config = { headers : { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;' } } var data = $.param({ first_name:"hello" }); $http.post("../api/account/ChangeUserName",data,config).then(function(response){...
Get 很正常,但不要貪圖方便用 get 來做什麼更換資料的 api, 這個很 87。
Angular-translate 多國翻譯,與帶來的後遺症製作 loading page 來解決它
下載來 angular-translate ,最基礎的用法就是:$translateProvider.useUrlLoader('/i18n/zh_TW.json'); //載入中文 $translateProvider.useUrlLoader('/i18n/en_US.json'); //載入英文 $translateProvider.preferredLanguage('zh_TW'); //設定預設語言是中文 ... 要變更的時候再到 controller 導入 $translate 。 (記得,剛剛那個是 provider ,是放在 angular.config 中的,這個是放 controller 的) $translate.use("en_US");
不過,如果你有幾百個語言,那大概會載入到爆炸,因此,你可以多下載一個官方再推出的 Angular Translate UrlLoader ,它的用法如下:
$translateProvider.useStaticFilesLoader({ prefix: 'i18n/locale-', suffix: '.json' }); ... $translate.use("en_US");
UrlLoader 這個模組可以讓你手動找到語言的後輟詞來找到這個語言檔案。
不過,用久了你就會發現
<p translate="">translate_hello</p> <p translate="translate_hello"><p> {{ "translate_hello" | translate }}
不管是那用法,都會出現翻譯的空白期,或是滿滿的識別字字串,非常難看。
這時候可以來製作一個 html loading 來搞定:
你可以在頁面載入之前,設定這個 loading 先處於顯示狀態,然後再 translate 翻譯完成後,將它關閉。
而這個事件為:
$rootScope.$on('$translateChangeSuccess', function () { $("#loading").hide(); console.log("TRANSLATE SUCCESSFULLY!"); });請務必把這段寫在最早次載入的 body 之類的地方,所加的 controller 中,並注意,這個事件是 $rootScope
沒有留言:
張貼留言