提问



我想使用AngularJS读取URL查询参数的值。我使用以下URL访问HTML:


http://127.0.0.1:8080/test.html?target=bob


正如所料,location.search"?target=bob"
为了访问 target 的值,我发现Web上列出了各种示例,但它们都不能在AngularJS 1.0.0rc10中运行。特别是,以下都是undefined:



  • $location.search.target

  • $location.search['target']

  • $location.search()['target']



谁知道什么会起作用? (我使用$location作为我的控制器的参数)





更新:


我在下面发布了一个解决方案,但我对此并不完全满意。
开发人员指南中的文档:Angular Services:使用$ location声明了以下$location:[46]



  我什么时候应该使用$ location?

  
  任何时候您的应用程序需要对当前的更改做出反应
  URL或者您想要在浏览器中更改当前URL。



对于我的场景,我的页面将从具有查询参数的外部网页打开,因此我不会对当前URL的更改做出本身。所以也许$location不是正确的工具工作(对于丑陋的细节,请参阅下面的答案)。因此我将这个问题的标题从如何使用$ location读取AngularJS中的查询参数?更改为什么是在AngularJS中读取查询参数最简洁的方法?。显然,我可以使用javascript和正则表达式来解析location.search,但是对于那些基本的东西来说,这种低级别实际上会冒犯我的程序员的敏感性。


所以:有没有比我在答案中更好的方式$location,还是有一个简洁的替代方案?

最佳参考


您可以将$ routeParams(需要ngRoute)注入控制器。这是文档中的一个例子:[47] [48]


// Given:
// URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
// Route: /Chapter/:chapterId/Section/:sectionId
//
// Then
$routeParams ==> {chapterId:1, sectionId:2, search:'moby'}


编辑:您还可以使用$ location服务(ng中提供)获取和设置查询参数,特别是其search方法:$ location.search()。 [49] [50]


在控制器的初始加载后,$ routeParams不太有用;可以随时调用$location.search()

其它参考1


很好,你已经设法使其与html5模式一起工作,但它也可以使其在hashbang模式下工作。


你可以简单地使用:


$location.search().target


访问目标搜索参数。


作为参考,这里是工作jsFiddle:http://web.archive.org/web/20130317065234/http://jsfiddle.net/PHnLb/7/[51]




var myApp = angular.module('myApp', []);

function MyCtrl($scope, $location) {

    $scope.location = $location;
    $scope.$watch('location.search()', function() {
        $scope.target = ($location.search()).target;
    }, true);

    $scope.changeTarget = function(name) {
        $location.search('target', name);
    }
}

<div ng-controller="MyCtrl">

    <a href="#!/test/?target=Bob">Bob</a>
    <a href="#!/test/?target=Paul">Paul</a>
    
    <hr/>    
    URL 'target' param getter: {{target}}<br>
    Full url: {{location.absUrl()}}
    <hr/>
    
    <button ng-click="changeTarget('Pawel')">target=Pawel</button>
    
</div>



为了回答我自己的问题,这里是HTML5浏览器的工作示例:


<!DOCTYPE html>
<html ng-app="myApp">
<head>
  <script src="http://code.angularjs.org/1.0.0rc10/angular-1.0.0rc10.js"></script>
  <script>
    angular.module('myApp', [], function($locationProvider) {
      $locationProvider.html5Mode(true);
    });
    function QueryCntl($scope, $location) {
      $scope.target = $location.search()['target'];
    }
  </script>
</head>
<body ng-controller="QueryCntl">

Target: {{target}}<br/>

</body>
</html>


关键是如上所述调用$locationProvider.html5Mode(true);。它现在在打开http://127.0.0.1:8080/test.html?target=bob时有效。我对它在旧浏览器中无法工作的事实感到高兴,但无论如何我都可以使用这种方法。


可以使用旧版浏览器的替代方法是删除html5mode(true)调用并使用以下地址和hash +斜杠:


http://127.0.0.1:8080/test.html#/?target=bob


相关文档位于开发人员指南:Angular Services:使用$ location(奇怪的是我的谷歌搜索没有找到这个......)。[52]

其它参考2


它可以通过两种方式完成:



  1. 使用$routeParams



最佳和推荐的解决方案是在控制器中使用$routeParams
它需要安装ngRoute模块。


   function MyController($scope, $routeParams) {
      // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
      // Route: /Chapter/:chapterId/Section/:sectionId
      // $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}
      var search = $routeParams.search;
  }



  1. 使用$location.search()



这里有一个警告。它仅适用于HTML5模式。默认情况下,它不适用于没有散列(#)的URL http://localhost/test?param1=abc&param2=def


您可以通过在URL中添加#/来使其工作。 http://localhost/test#/?param1=abc&param2=def


$location.search()返回一个像这样的对象:


{
  param1: 'abc',
  param2: 'def'
}

其它参考3


$ location.search()仅适用于打开HTML5模式且仅支持浏览器。


这将始终有效:


$ window.location.search

其它参考4


只是为了总结一下。


如果您的应用程序是从外部链接加载的,那么angular不会将其检测为URL更改,因此$ loaction.search()将为您提供一个空对象。要解决此问题,您需要在应用配置(app.js)中设置以下内容


.config(['$routeProvider', '$locationProvider', function ($routeProvider,     $locationProvider) 
{
   $routeProvider
      .when('/', {
         templateUrl: 'views/main.html',
         controller: 'MainCtrl'
      })
      .otherwise({
         redirectTo: '/'
      });

      $locationProvider.html5Mode(true);
 }]);

其它参考5


只是精确到埃利斯怀特黑德的答案。$locationProvider.html5Mode(true);不能使用新版本的angularjs而不用<base href="">标签指定应用程序的基本URL或将参数requireBase设置为false


来自文件:[53]



  如果将$ location配置为使用html5Mode(history.pushState),则需要使用标记指定应用程序的基本URL,或者通过将带有requireBase:false的定义对象传递给$ locationProvider来将$ locationProvider配置为不需要基本标记。 html5Mode():



$locationProvider.html5Mode({
  enabled: true,
  requireBase: false
});

其它参考6


你也可以使用$ location。$$ search.yourparameter

其它参考7


这可能对你有所帮助


什么是在AngularJS中读取查询参数最简洁的方法


// Given:
// URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
// Route: /Chapter/:chapterId/Section/:sectionId
//
// Then
$routeParams ==> {chapterId:1, sectionId:2, search:'moby'}

<!DOCTYPE html>
<html ng-app="myApp">
<head>
  <script src="http://code.angularjs.org/1.0.0rc10/angular-1.0.0rc10.js"></script>
  <script>
    angular.module('myApp', [], function($locationProvider) {
      $locationProvider.html5Mode(true);
    });
    function QueryCntl($scope, $location) {
      $scope.target = $location.search()['target'];
    }
  </script>
</head>
<body ng-controller="QueryCntl">

Target: {{target}}<br/>

</body>
</html>

($location.search()).target

其它参考8


我发现对于SPA HTML5Mode会导致很多404错误问题,并且在这种情况下没有必要使$ location.search工作。在我的情况下,我想在用户访问我的网站时捕获URL查询字符串参数,无论他们最初链接到哪个页面,并且能够在他们登录后将它们发送到该页面。所以我只是捕获所有在app.run中的东西


$rootScope.$on('$stateChangeStart', function (e, toState, toParams, fromState, fromParams) {
    if (fromState.name === "") {
        e.preventDefault();
        $rootScope.initialPage = toState.name;
        $rootScope.initialParams = toParams;
        return;
    }
    if ($location.search().hasOwnProperty('role')) {
        $rootScope.roleParameter = $location.search()['role'];
    }
    ...
}


然后登录后我可以说
    $ state.go($ rootScope.initialPage,$ rootScope.initialParams)

其它参考9


这有点晚了,但我认为你的问题是你的网址。如果不是


http://127.0.0.1:8080/test.html?target=bob


你有过


http://127.0.0.1:8080/test.html#/?target=bob


我很确定它会起作用.Angular对它的#/非常挑剔#/