AngularJS-处理手动输入URL状态的最佳方式

AngularJS - Best Way to Handle State on Manually Entered URLs

本文关键字:最佳 方式 状态 URL 处理 手动输入 AngularJS-      更新时间:2023-09-26

我目前有一个基于meanjs堆栈样板的设置,在这里我可以让用户在浏览网站URL时处于"登录"状态。这是由于将用户对象保存在全局可用的服务中。

然而,只有当我从我的基本根目录(即从"/"和仅在我的应用程序中导航)进行导航时,这才有效。

如果我手动输入诸如"/page1"之类的URL,它将丢失全局用户对象,但是,如果我转到根主页并通过网站导航到"/pages1"。然后就可以了,它在Service对象中看到全局用户对象。

所以我想这是由于整个页面刷新会丢失全局值,而通过网站导航时不会进行刷新,因此您保留了所有变量。

需要注意的一些事项:

  1. 我已启用HTML5Mode,使用前缀"!"
  2. 我使用UI路由器
  3. 我使用带有"/"的标记
  4. 我在express上有一个重写规则,在加载所有路由后,我有最后一个路由,它将所有"/*"都带到根index.html文件并发送回,因为angularjs的东西就在那里

我只是想知道这里的人们通常都做什么?他们是否恢复标准cookie和本地存储解决方案?我对angular还很陌生,所以我猜有一些库可以做这件事。

我只是想知道处理这件事的建议方法是什么,或者大多数人会怎么做,这样我就可以以正确的方式和有角度的方式保持一致。

更新:

如果我通过地址栏手动导航到我的网站上的另一个URL,我会丢失我的用户状态,但是如果我手动通过地址栏返回到我的根目录,我的用户状况会再次出现,所以这不仅仅是在窗口刷新时丢失状态。所以它似乎和根URL上运行的代码有关。

我有一个明确的重写,手动输入的URL(由于HTML5定位模式)应该首先返回index.html,因为它包含AngularJs文件,然后UI路由接管并正确路由它。

所以我本以为根上的任何代码都会执行,所以它应该类似于通过网站导航或在地址栏中键入。我一定错过了一些关于Angular的有这种效果的东西。

更新2

是的,所以更多的调查让我想到了这个:

<script type="text/javascript">
    var user = {{ user | json | safe }};
</script>

这是index.html的服务器端代码,我想在通过手动URL将页面刷新到新页面时不会运行。

使用hash bang模式,它是有效的,这是因为使用hash bang模式,即使我在浏览器中键入URL,它也不会引起刷新,而使用HTML5模式时,它确实会刷新。所以现在我能想到的解决方案是使用sessionStorage。

除非有更好的选择?

更新3:

在使用HTML5Mode时,处理这一问题的最佳方法似乎是,您只需要在express服务器上重写一次,而不需要做其他事情。

我认为你说得对,但你可能想看看你的应用程序可能需要的所有路线,只考虑一些基本结构(api、用户、会话、部分等)。这似乎是一个问题,它就像你想让它变得多么复杂。

就最佳实践而言,您可以遵循角全堆栈生成器或meanio项目。

你所做的看起来最接近平均值。io主要是因为他们也使用ui路由器,尽管他们似乎保留了hashbang,而且它看起来更像是一个SEO友好型,具有一些独立的SPA页面功能。你可能可以安装它并在我在这里解释之前找到代码,所以-

npm install -g meanio
mean init name
cd [name] && npm install

有角度的全栈看起来像这样,这是一个更典型的路由的好例子:

// Server API Routes
app.route('/api/awesomeThings')
  .get(api.awesomeThings);
app.route('/api/users')
  .post(users.create)
  .put(users.changePassword);
app.route('/api/users/me')
  .get(users.me);
app.route('/api/users/:id')
  .get(users.show);
app.route('/api/session')
  .post(session.login)
  .delete(session.logout);
// All undefined api routes should return a 404
app.route('/api/*')
  .get(function(req, res) {
    res.send(404);
});
// All other routes to use Angular routing in app/scripts/app.js
app.route('/partials/*')
  .get(index.partials);
app.route('/*')
  .get( middleware.setUserCookie, index.index);

然后,为了简单起见,使用一些正则表达式找到部分,并在不进行渲染的情况下交付,如:

var path = require('path');
exports.partials = function(req, res) {
 var stripped = req.url.split('.')[0];
 var requestedView = path.join('./', stripped);
 res.render(requestedView, function(err, html) {
   if(err) {
     console.log("Error rendering partial '" + requestedView + "''n", err);
     res.status(404);
     res.send(404);
   } else {
     res.send(html);
   }
 });
};

并且索引被呈现:

exports.index = function(req, res) {
  res.render('index');
};

最后,我确实遇到了一些麻烦,但通过做一些可以分解为步骤的事情,我成功地让它发挥了作用,这些步骤适用于那些使用HTML5Mode的人。

1)在Angular中启用HTML5Mode后,在服务器上设置重写,以便它发回包含Angular src-js文件的index.html。注意,这个re-write应该在静态文件和正常服务器路由之后(例如,在REST API路由之后)。

2)确保角度路由与服务器路由不同。因此,如果你有一个前端状态/user/帐户,那么就没有服务器路由/user/账户,否则它将不会被调用,请将你的服务器端路由更改为/api/v1/server/route。

3)对于前端中所有旨在触发对服务器的直接调用而不必经过角度状态/路由的锚标记,请确保添加"target=_self"。