【问题标题】:Angular JS and Node routing/wiring - data only showing after a page refreshAngular JS 和节点路由/布线 - 数据仅在页面刷新后显示
【发布时间】:2026-02-20 05:15:01
【问题描述】:

我正在使用 Node 和 Anugular,并且我从我的应用程序中创建了一个 RESTful api,并创建了一个 Angular 资源来使用它。我对 Angular ui-router 指令如何与服务器上的节点路由系统协调感到困惑。

目前我已经在 ui-router 中设置了我的路由/状态,如下所示:

$stateProvier
.state('admin', {
            url:'/admin',
            templateUrl:'views/admin.html', 
            controller: 'adminController'
        });

当我从加载页面上的链接导航到此 url 时,这会加载到我主页上的 ui 视图中。

但是,当我手动输入 localhost/admin 时,我会从 Node 获取路由,而不是通过 angular 渲染状态。

现在,我希望 Angular 处理我的应用程序上的所有导航,以及获取信息的资源,即使地址是手动输入到导航栏中的。

我在 Node 中为 index 创建了一个路由,其中​​包含我来自 angular 的 index.html 页面,它有效地包含了整个应用 Angular 代码,包括所有路由。

我的问题是,如果我在地址栏中手动输入 url,并且仍然有来自 $resource 的数据,如何获得角度重定向。

我正在将我的资源定向到“/admin” - 这可能是问题所在吗?

这是否意味着我需要将 /routes/appointments' 的内容添加到基本节点文件(server.js)中,然后删除路由?如果是这样,那么我如何将我的资源定向到正确的 REST api?

应用结构

公开 -角度应用程序 -app.js //对于角度 路线 index.js 约会.js 楷模 意见 - index.ejs server.js //节点服务器文件

这是我的代码摘录 server.js

//standard routing code
var routes = require('./routes/index');
var appointments = require('./routes/appointments');

var app = express();
//configuring Express
app.set('port', process.env.PORT || 3000);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.use('/', routes);
app.use('/', appointments);

路由/index.js

var express = require('express');
var router = express.Router();

// ./routes/index.js
router.get('/', function(req, res) {
  res.render('index', { title: 'Homepage' });
});

module.exports = router;

routes/appointments.js - 这是我的 RESTFUL api 的基础

var express = require('express');
var router = express.Router();

var mongoose = require('mongoose');
var Todo = require('../models/Appointments.js');

/* GET /todos listing. */
router.get('/admin', function(req, res, next) {
  Todo.find(function (err, todos) {
    if (err) return next(err);
    res.json(todos);
  });
});

module.exports = router;

【问题讨论】:

    标签: javascript angularjs node.js url-routing


    【解决方案1】:

    一种方法是通过 Accept 标头。如果请求仅接受 JSON,则让请求通过您的 API。如果请求接受 HTML,则始终提供您的索引页面。然后,一旦索引页面加载,Angular 的路由器就会处理剩下的事情。

    // Angular config - default Accept header for all ajax requests
    $httpProvider.defaults.headers.common = {
        'Accept': 'application/json'
    };
    
    // Middleware in Node to "intercept" non JSON requests
    // Place this after express.static middleware but before your route definitions.
    app.use(function(req, res, next) {
    
        // keep in mind this applies to all requests, so 404s will need to be handled by your angular app since any url will serve up the index page
        if(req.header('Accept') !== 'application/json') {
            console.log('serving the index page');
            req.url = '/'; // force the url to serve the index route.
        }
    
        next();
    
    });
    

    关于这种方法还有一点需要注意的是,显然您将无法再通过直接点击 URL 来查看/调试 JSON 数据。有几个有用的工具,例如 Advanced REST Client 或 POSTman,它们实际上可以为您提供更好的控制和更多的选择。只需确保您在其中一个工具中设置了 Accept 标头,您就可以看到 JSON 响应。

    【讨论】:

    • 嘿 Ryan - 谢谢你 - 但这会导致意外错误 - 我正在使用 ui-router - 现在如果我链接到任何将 id 传递给 stateParam 的页面,我仍然重定向,因为这不是应用程序/json 类型的标头 - 我如何使用此方法但仍将 stateParams 传递给 ui-router?
    • 你能给我一个你试图访问的 URL 的例子吗?我不确定我是否理解这个问题。
    【解决方案2】:

    实际网址是localhost#!/admin,试试看。 Angular 隐藏了 hashbang #!

    Angular 的 URL 路由在这种情况下是一种“错觉”。它仅适用于客户端,并且仅在加载您的 Angular 应用程序时才有效,该应用程序位于主 / 路由上。

    解决方案可能是有条件地从 localhost/admin 重定向到 localhost#!/admin,即重定向到您的 Angular 应用程序并传递 it #!/admin 路径。条件可以是检查是否请求了 JSON。

    router.get('/admin', function(req, res, next) {
      if(req.header('Accept') !== 'application/json')
        return res.redirect('/#!/admin');
      Todo.find(function (err, todos) {
        if (err) return next(err);
        res.json(todos);
      });
    });
    

    您还需要配置 Angular,以便当它从服务器请求“/admin”json 数据时,它应该只接受 json(通过设置请求标头),这是服务器将它与常规 '/admin' 请求。为此,如果您使用$http.get,您将使用$http.get('/admin', {'Accept':'application/json'})

    【讨论】:

    • 嗨 laggingreflex - 谢谢你 - 但现在我无法从后端获取数据以在页面上呈现 - 我尝试使用 Postman 进行检查,但在都回来了
    • 很可能您还需要配置 Angular,以便当它从服务器请求“/admin”json 数据时,它应该只接受 json(通过设置请求标头),即服务器如何将其与常规的“/admin”请求区分开来。为此,如果您使用$http.get,您将使用$http.get('/admin', {'Accept':'application/json'})
    • 太好了 - 我怎么能用 $resource 做到这一点