Ответ 1
Хорошо, мне удалось найти решение, работающее с текущей стабильной версией (@1.0.7).
В текущем способе решения этой проблемы будут связаны события, связанные с трафиком, разбора angular -независимых URL-адресов на лету и обработки их с помощью дополнительной службы, работающей аналогично перехвату $http.
Здесь вы можете увидеть примеры рабочих кодов: http://embed.plnkr.co/fIA2xj/preview
Основные шаги
- передайте angular -независимый URL-адрес, как обычно, например. перейдите на сайт site.com/url/http://site.com
- прослушать событие $routeChangeStart и извлечь правильный URL-адрес для путей, начинающихся с
/url/
- закодировать правильный параметр url в angular -патентной форме (в данном конкретном случае я использую base64). Не используйте encodeURIComponent, потому что angular будет обрабатывать как любой другой URL
- перенаправлять на другой маршрут с помощью бизнес-логики, например. site.com/parsed-url/BASE64_GOES_HERE
- декодировать URL-адрес в контроллере и использовать его как обычно:)
код
Создайте модуль приложения angular как обычно
angular.module('routes',[]).config([
'$routeProvider',
function($routeProvider){
$routeProvider
.when('/test', {templateUrl: 'test.html'})
// This one is important:
// We define a route that will be used internally and handle
// parameters with urls parsed by us via the URLInterceptor service
.when('/parsed-url/:url', {templateUrl: 'url.html', controller:'URLCtrl'})
.when('/', {redirectTo: '/test'})
.otherwise({templateUrl: '404.html'});
}
])
Служба перехвата URL (singleton)
.service('URLInterceptor', function($rootScope, $location){
// We listen to $routeChangeStart event and intercept it if
// the path matches our url scheme. In this case, every route
// beginning with /url/ will be caught
$rootScope.$on('$routeChangeStart', function(e, next, current){
// $location.path does change BEFORE actual routing happens,
// so in this case we get parsed new location object
// for free.
// To be hones, a better way of handling this case might be using
// $locationChangeStart event instead, but it would require us to parse urls
// manually.
var path = $location.path();
// check if string begins with '/url/'
var matcher = path.slice(0,5);
var cleanPath = '';
if (matcher === '/url/'){
// Yes it does, yay!
// Remove leading '/url/' to extract the actual parameter
cleanPath = path.slice(5);
// Encode our url to a safe version. We know that encodeURIComponent won't
// work either, so a good choice might be base64.
// I'm using https://code.google.com/p/javascriptbase64/downloads
$location.path('/parsed-url/' + Base64.encode(cleanPath));
// Prevent default event execution. Note that, it won't cancel related $location Events
e.preventDefault();
}
});
return {
decode: Base64.decode,
encode: Base64.encode
}
})
Контроллеры
// Main application controller
// We instantiate our URLInterceptor service here
.controller('AppCtrl',function($scope, $location, URLInterceptor){
$scope.navigateTo = function (path) {
$location.path('/url/' + path);
}
})
.controller('URLCtrl', function($scope, $routeParams, URLInterceptor){
$scope.url = URLInterceptor.decode($routeParams.url);
});
Две вещи, которые вы должны запомнить:
- Хотя я пытался создать решение как можно более чистым, обычно передача данных таким образом, чтобы angular не считается хорошей практикой, поэтому постарайтесь не использовать его, если вам действительно не нужно.
- Вы можете справиться с этой проблемой только одним маршрутом. Я просто считаю это более чистым.