我正在将一个由其他人制作的小型现有Angular JS应用程序集成到一个不是使用Angular构建的现有网站中。
所有Angular JS应用程序文件都保存在一个完全独立的目录中,然后用户可以单击链接将它们带到该子目录的索引。例如:
<a href="/path/to/angular-app/?returnUrl=/original/location">Login.</a>
如上所示,我需要传递一个名为returnUrl
的URL参数。然后我需要在Angular JS应用程序中使用:
$location.search()
然而,这实际上返回一个空对象。我认为这是因为Angular JS在 URL参数之后在URL 上附加#!/login
,如下所示:
example.com/path/to/app?returnUrl=/original/location/#!/login
如果我在浏览器中修改了网址,将returnUrl
参数移到了网址的末尾并刷新了网页,则可以正常工作,$location.search()
会返回{returnUrl: "/original/location/"}
。但是,据我所知,我无法在我的网站中更改此内容,因为该参数是Angular JS应用程序链接的一部分,之后会自动添加#!/login
。
我是新的AngularJS,所以请尽可能清楚地解释:
#!/login
?$location.search()
返回任何内容?如果我将参数移动到结果URL的末尾,它就会起作用。答案 0 :(得分:3)
您只需使用window.location.search
> window.location.search
> "?returnUrl=/original/location/"
$location.search()
仅在路线定义了值时为您提供值。
答案 1 :(得分:2)
这里发生了什么?为什么#!/ login?
之前的URL参数
您可以将#!之前的查询字符串参数视为服务器端参数,并将#!之后的查询字符串参数视为< em>客户端参数。这完全有效:
http://example.com?serverParam=client1#!angularRoute?angularParam=someValue
服务器端参数允许您配置从服务器提供页面的方式,然后,在提供服务器页面并加载Angular应用程序后,使用客户端参数提供特定Angular应用程序所期望的内容。
为什么这会阻止$ location.search()返回任何内容?如果我 将参数移动到结果URL的末尾,它可以工作。
因为在您移动值之前没有为客户端参数指定任何内容。
我该怎么做才能解决这个问题?
<a href="example.com/path/to/app/#!/login?returnUrl=/original/location">Login.</a>
$window
并从中获取服务器端值
$window.location.search
$location
并使用$location.absUrl()
以下是如何从服务器端参数设置客户端参数的示例:
var app = angular.module('YOURAPPNAME', []);
app.run(['$location', function($location) {
// I'm going to fake out the url so it runs in the SnippetEditor.
var url = "example.com/path/to/app?returnUrl=/original/location/#!/login"; //$location.absUrl();
var hashbangIdx = url.indexOf('#!');
var serverStr = hashbangIdx > -1 ? url.substring(0, hashbangIdx) : url;
var qIdx = serverStr.indexOf("?");
var p = qIdx > -1 ? serverStr.substring(qIdx).split(/[&||?]/) : [];
for (var i = 0; i < p.length; i += 1) {
if (p[i].indexOf('=') > -1) {
var param = p[i].split('=');
$location.search(param[0], param[1]);
}
}
}]);
app.controller('MainCtrl', ['$scope', '$location', function($scope, $location) {
$scope.params = $location.search();
}]);
<!DOCTYPE html>
<html ng-app="YOURAPPNAME">
<head>
<meta charset="utf-8" />
<title>AngularJS</title>
<script data-require="angular.js@1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<h4>Parameters:</h4>
<p ng-repeat="(name, val) in params">
{{name}}: {{val}}
</p>
</body>
</html>
答案 2 :(得分:1)
以下是您的问题的答案:
1)AngularJS将#添加到加载页面的URL的末尾。因此,如果加载页面的url已经具有returnUrl的查询参数,这似乎就是这种情况,它将始终显示在#的左侧。
2)AngularJS应用程序通常只关注url中#后面发生的事情。 AngularJS使用它来在状态和更类似的东西之间路由和传递查询参数。 $ location.search()用于检索#。
之后的所有查询参数3)以下是如何提取在#
之前发生的查询参数function getParamFromURL (paramName) {
var searchStr = window.location.search.substring(1);
var keyValues = searchStr.split('&');
for(var i=0; i<keyValues.length; i++) {
var split = keyValues[i].split('=');
if(split[0] === paramName) {
return decodeURIComponent(split[1]);
}
}
}
var value = getParamFromURL('returnUrl');
console.log(value);
答案 3 :(得分:1)
您在网址中看到的#
实际上是什么称为锚链接或片段。通常通过其ID跳转到特定元素,例如,如果您的元素与此ID匹配,则导航点击<a href="#footer">
将直接滚动您的页面。
Angular和其他框架(如React)利用此功能通过将哈希用作当前活动路由来创建所谓的哈希路由。这样做的好处是它可以实现非常快速的设置,并且可以在非HTML5浏览器上开箱即用。
关于查询参数在哈希之前的原因,只是因为它实际上是您在链接中指定的内容。 Angular会将您正在加载的url视为项目的根目录,并在初始化后将当前路由器添加自己的#
。您可能只有在指定此查询参数时才有服务器为Angular应用程序提供服务,因此保持其位置的重要性。如果查询参数位于哈希之后,则它被视为Angular应用程序路由的一部分,因此在您调用$location.search()
时会返回。
我建议您做的是在链接中明确指定#
,或使用html5模式。 Html5模式意味着您不会在您的网址中获取哈希表单,而不是#34;正常&#34;那些不那么难看的。
为此,您必须在应用中启用html5模式
.config(function ($locationProvider) {
$locationProvider.html5Mode(true);
}
并在脑中添加元库
<base href="/" />
问题是,现在,如果您尝试加载不是主页的页面,您将会遇到404问题。
为防止这种情况发生,您必须为应用程序的每个子路径提供Angular条目。有多种方法,具体取决于您在服务器上使用/想要使用的内容。这是展示大部分内容的the Angular FAQ。
答案 4 :(得分:1)
您可以使用$location.absUrl():它将返回完整的网址,其中所有网段均按照RFC 3986中指定的规则进行编码。
var resultURl = GetURLParameter('returnUrl');
console.log(resultURl);
function GetURLParameter(param) {
// var URL = $location.absUrl();
var URL = "example.com/path/to/app?returnUrl=/original/location/#!/login";
var allVariables = URL.split('?');
for (var i = 0; i < allVariables.length; i++) {
var paramName = allVariables[i].split('=');
if (paramName[0] == param) {
return paramName[1].split("#")[0];
}
}
}
============================== 或 ========= ===========================
RouteProvider
和routeParams
适用于您的情况。
您可以在路由中将returnUrl
作为路由参数传递,然后使用$routeParams.returnUrl
返回控制器。
我该怎么做才能解决这个问题?
您可以尝试这种方法来解决此问题。
HTML:
<a href="#login/original/location">Login Return Url</a>
路由文件:
$routeProvider.when('/login/:returnUrl', {
templateUrl: 'partials/partial.html',
controller: 'MyCtrl'
});
在控制器中,注入$routeParams
:
.controller('MyCtrl', ['$scope','$routeParams', function($scope, $routeParams) {
var url = $routeParams.returnUrl;
}]);
注意:
如果您使用的是ngRoute
,则可以将$routeParams注入您的控制器。
如果您使用的是angular-ui-router
,则可以将$stateParams注入您的控制器。
答案 5 :(得分:-1)
检查一下,
function getValue(key, url) {
var regex = new RegExp("[?&]" + key + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
return results[2];
}
var value = getValue("returnUrl","example.com/path/to/app?returnUrl=/original/location/#!/login");
console.log(value);