javascript 如何使 Angularjs 路由与 html5mode 上的 expressJs 路由一起使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19609908/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to make Angularjs route work with expressJs route on html5mode
提问by John Lim
i have posted a question on stackoverflow (css and javascript didn't include on refresh) yesterday asking the question about why the css and javascript didn't include on my webpage after I refresh the webpage and found out it caused by the html5mode, so i have been searching the solution for this problem since yesterday but I can't really get an answer.
我昨天在 stackoverflow 上发布了一个问题(css 和 javascript 没有包含在刷新中)昨天询问了为什么在我刷新网页并发现它是由 html5mode 引起的 css 和 javascript 没有包含在我的网页上的问题,所以从昨天开始我一直在寻找这个问题的解决方案,但我真的找不到答案。
my folder structure
我的文件夹结构
app.js
应用程序.js
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, mongoose = require('mongoose');
var app = module.exports=express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/public/views');
app.set('view engine', 'ejs');
app.use(express.cookieParser());
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(path.join(__dirname, 'public')));
app.use(app.router);
app.use(function(request, response)
{
console.log("catch all");
writeFile("/public/views/master.ejs", request, response);
});
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.use(function (req,res) {
res.status(404).render('error', {
url: req.originalUrl
});
});
app.get('/', routes.index);
app.get('/:name', routes.view);
app.get('*', routes.risk);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
index.js
索引.js
exports.index = function(req, res){
res.render('master', { title: 'Hello World' });
};
exports.view = function (req, res) {
var name = req.params.name;
res.render(name);
};
exports.risk = function(req, res){
res.sendfile(__dirname + "/public/views/master.ejs");
};
for the exports.risk i was trying to make the expressJs to render the master page 1st before it renders other but it doesn't work.
对于exports.risk,我试图让expressJs 在呈现其他页面之前先呈现母版页,但它不起作用。
angularJs
角Js
var SymSal = angular.module('SymSal',[]).
config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.
when('/', {
templateUrl: 'main.ejs',
controller: 'IndexCtrl'
}).
when('/login',{
templateUrl: 'login.ejs',
controller: 'IndexCtrl'
}).
when('/register',{
templateUrl: 'register.ejs',
controller: 'IndexCtrl'
}).
when('/about',{
templateUrl: 'about.ejs',
controller: 'IndexCtrl'
}).
otherwise({
templateUrl: 'error.ejs'
});
$locationProvider.html5Mode(true);
}]);
SymSal.controller('IndexCtrl',function(){
})
Your help is appreciated, THANK YOU !!
感谢您的帮助,谢谢!!
回答by bekite
for the exports.risk i was trying to make the expressJs to render the master page 1st before it renders other but it doesn't work.
对于exports.risk,我试图让expressJs 在呈现其他页面之前先呈现母版页,但它不起作用。
Routes are matched in sequential order:
路由按顺序匹配:
app.get('/', routes.index);
app.get('/:name', routes.view);
app.get('*', routes.risk);
If the route matches '/' render routes.index. If the route doesn't match '/' check if it matches '/:name' (e.g. /login, /register) and render routes.view. If the route doesn't match '/' and '/:name' (e.g. route is something like /user/1) routes.risk will be rendered.
如果路由匹配'/',则渲染routes.index。如果路由不匹配'/',检查它是否匹配'/:name'(例如/login、/register)并渲染routes.view。如果路由不匹配 '/' 和 '/:name'(例如路由类似于 /user/1) routes.risk 将被渲染。
To make express render the master page first you need to remove the route matcher for '/' and '/:name' and keep the universal matcher ('*') that will match every route.
要首先快速渲染母版页,您需要删除“/”和“/:name”的路由匹配器,并保留将匹配每条路由的通用匹配器 (“*”)。
Now the server will send back the master page no matter what url you provide. If you call localhost:3000/login the server will send back the master page (same page as is if you would call localhost:3000). Angular will see that a path (/login) is specified and will call the appropriate $routeProvider.when() function.
现在,无论您提供什么 url,服务器都会发回母版页。如果您调用 localhost:3000/login,服务器将发回母版页(与您调用 localhost:3000 时的页面相同)。Angular 将看到指定了路径 (/login) 并将调用适当的 $routeProvider.when() 函数。
To handle api calls (like get data from db, save data to db) you need to specify a route matcher for this and place it above the universal matcher ('*'):
要处理 api 调用(例如从数据库获取数据,将数据保存到数据库),您需要为此指定一个路由匹配器并将其放置在通用匹配器('*')之上:
app.get('/api', routes.api);
It's important to mention that you don't use '/api' in your $routeProvider.when().
值得一提的是,您没有在 $routeProvider.when() 中使用“/api”。
What's left is the correct handling of static files: Remember every url is handled by the universal matcher ('*'). So static files get render with the wrong MIME type. To fix this, you need to make all static files accessible under a specific path e.g '/static'. Simply update
剩下的是正确处理静态文件:记住每个 url 都是由通用匹配器 ('*') 处理的。因此静态文件使用错误的 MIME 类型进行渲染。要解决此问题,您需要使所有静态文件都可以在特定路径下访问,例如“/static”。只需更新
app.use(express.static(path.join(__dirname, 'public')));
to
到
app.use('/static', express.static(path.join(__dirname, 'public')));
You need to update all paths in your master page to match the new pattern: '/js/angular.js' is now '/static/js/angular.js'
您需要更新母版页中的所有路径以匹配新模式:'/js/angular.js' 现在是 '/static/js/angular.js'
回答by dharmatron
Thanks to @bekite for the basis of a plausible solution. Building on his initial solution, I've found the following a little cleaner for myself, and it avoids needing to update and maintain all your paths with a /static
prefix. Note that the app.get('*', routes.risk)
did not work for me (Express v3.4.4), however using a regex did:
感谢@bekite 提供了合理解决方案的基础。在他最初的解决方案的基础上,我发现以下内容对我自己来说更清晰,它避免了需要使用/static
前缀更新和维护所有路径。请注意,这app.get('*', routes.risk)
对我不起作用(Express v3.4.4),但是使用正则表达式可以:
...
app.use(app.router);
app.use(express.static(path.join(__dirname, 'app')));
// Express routes - ensure these are not defined in Angular's app.js $routeProvider:
app.get('/api', routes.api);
/**
* ANGULAR APP ROUTING
* --------------------
* These routes will fallback to Angular for resolution of any uri:
* Note that the * wildcard will not work, hence the alternate regex
* It is crucial that 'static' assets never be referenced with a leading
* forward slash '/', else they'll match this rule and 404's will occur
*/
//app.get('*', routes.risk);
app.get('/[a-z]{0,100}', routes.risk);
////
// alternatively:
//
// app.get('/[a-z]{0,100}', function(req, res) {
// res.sendfile('app/index.html', {title: 'Default Title', stuff: 'More stuff to send to angular'}
// });
...
As per @bekite, Angular paths are passed through to a generic route (which may provide further branching if desired), and captured by the Angular $routeProvider. Express paths are caught with the /api
prefix and processed server-side as needed.
根据@bekite,Angular 路径被传递到通用路由(如果需要,可以提供进一步的分支),并由 Angular $routeProvider 捕获。使用/api
前缀捕获快速路径并根据需要在服务器端进行处理。