当在浏览器中直接访问 URL 但单击到时,角度路由不起作用?

Posted

技术标签:

【中文标题】当在浏览器中直接访问 URL 但单击到时,角度路由不起作用?【英文标题】:Angular routing doesn't work when URL is directly visited in browser but works when clicked to? 【发布时间】:2013-12-25 21:05:48 【问题描述】:

我有一个带有目录结构的 Angular 应用程序

app 
..views
....partials
......main.jade
......foo.jade
....index.jade

路由定义如下:

'使用严格';

angular.module('myApp', [
  'ngCookies',
  'ngResource',
  'ngSanitize',
  'ngRoute', 
  'firebase', 
  'myApp.config'
])
  .config(function ($routeProvider, $locationProvider) 
    $locationProvider.html5Mode(true);  

    $routeProvider
      .when('/', 
        templateUrl: '/partials/main',
        controller: 'MainCtrl'
      )
      .when('/foo/:fooName', 
        templateUrl: '/partials/foo',
        controller: 'FooCtrl'
      )            
      .otherwise(
        redirectTo: '/'
      );
  );

我在服务器端使用express,相关代码是:

    // server.js 
   app.configure('development', function()
     app.use(express.static(path.join(__dirname, '.tmp')));
     app.use(express.static(path.join(__dirname, 'app')));
     app.use(express.errorHandler());
   );

   app.configure('production', function()
    app.use(express.favicon(path.join(__dirname, 'public/favicon.ico')));
    app.use(express.static(path.join(__dirname, 'public')));
   );

    app.get('/', routes.index);
    app.get('/partials/:name', routes.partials);

    //routes.js
    exports.index = function(req, res)
      res.render('index');
    ;


    exports.partials = function(req, res)
      var name = req.params.name;
      res.render('partials/' + name);
    ;

主要路线"/" 加载正常,当我单击"/foo/bar" 时,部分视图foo.jade 会按预期加载。但是,当我尝试直接在 URL 中访问 "/foo/bar" 时,我得到了来自 Express "cannot GET /foo/bar" 的 404 响应,这是有道理的,因为 express 中没有这样定义的路由。但是,我认为这是定义角度路由器的重点......即它应该拦截这个请求并实际请求"/partials/foo"。 我尝试添加

//redirect all others to the index (HTML5 history)
app.get('*', routes.index);

但它并没有解决问题,并且似乎甚至可以捕获对静态 js 资产的请求并以 index.html 的内容进行响应,这非常糟糕。 我确定我做错了什么。如何解决问题以便可以直接访问 URL?

【问题讨论】:

【参考方案1】:

路由出现这种行为的原因是打开了 html5mode。 注意这一行:$locationProvider.html5Mode(true);

您需要了解,当您尝试直接访问"/foo/bar" 时,您的浏览器会向该 URL 发送 HTTP GET 请求。当您尝试通过单击链接访问此 url 时,如您所说,Angular 正在拦截此操作并调用仅更新浏览器链接的 History.pushState。

为了使 html5mode 路由工作,您需要做的是实现 url 重写。每个请求都必须重定向到引导 AngularJS 应用程序的索引文件,但这需要在您的服务器上完成。 Angular 将自己呈现所需的页面。

查看connect mod rewrite grunt 任务,它确实做到了。

你也可以直接this middleware 。

【讨论】:

但我尝试在服务器上执行此操作:app.get('*', routes.index);这没有用。 我认为你做不到。如果您使用的是 express,connect-mod-rewrite 应该很容易使用。 Express 写在 connect 之上。 但这正是这里所做的:github.com/btford/angular-express-seed/blob/master/app.js,这是标准的 Angular 参考。为什么它在这种情况下有效?

以上是关于当在浏览器中直接访问 URL 但单击到时,角度路由不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

在页面刷新和 url 重写的角度路由后,cookie 的计数为零

当在角度 4 中触发事件时,将属性的值从指令重置为默认值

router.navigate(url) 不加载组件,但直接在浏览器中输入 url

如何使用角度检测浏览器后退按钮单击事件?

角度路由更改后量角器找不到元素

Flutter Web 和 Django 直接从 URL 路由