好的,我设法找到了一个适用于当前稳定版本(@1.0.7)的解决方案。
当前处理此问题的方法将涉及与 $route 相关的事件,动态解析 angular-incompatible url 并通过以类似于 $http 拦截的方式工作的附加服务来处理它们。
您可以在此处查看工作代码示例:http: //embed.plnkr.co/fIA2xj/preview
主要步骤
- 像往常一样传递一个角度不兼容的网址,例如。转到 site.com/url/ http://site.com
- 监听 $routeChangeStart 事件并为以开头的路径提取正确的 url 参数
/url/
- 将正确的 url 参数编码为角度兼容的形式(在这种特殊情况下,我使用 base64)。不要使用 encodeURIComponent,因为 Angular 将视为任何其他 url
- 使用您的业务逻辑重定向到另一条路线,例如。site.com/parsed-url/BASE64_GOES_HERE
- 解码控制器中的 URL 并像往常一样使用它:)
代码
像往常一样创建角度应用程序模块
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 拦截器服务(单例)
.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 并不是一个好的做法,所以除非你真的需要,否则尽量不要使用它。
- 您可以仅使用一条路线处理此问题。我只是觉得这样更干净。