Я использую Angular 1.3.10, ui-router 0.2.10 и Express 4.14.0 для базового клона Reddit, и у меня возникают проблемы с маршрутизацией.
Мой (сокращенный) Экспресс-маршруты:
router.get('/api/home', function (req, res, next) {
res.render('index', {
title: 'Meanit'
});
});
router.get('*', function (req, res, next) {
res.redirect('/api/home');
});
Моя конфигурация углового состояния:
app.config([
'$stateProvider',
'$urlRouterProvider',
'$locationProvider',
function ($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/views/home.html',
controller: 'MainCtrl',
resolve: {
postPromise: [
'posts',
function (posts) {
return posts.getAllPosts();
}
]
}
})
.state('posts', {
url: '/posts/{id}',
templateUrl: '/views/posts.html',
controller: 'PostsCtrl',
resolve: {
post: [
'$stateParams',
'posts',
function ($stateParams, posts) {
return posts.getPost($stateParams.id);
}
]
}
})
.state('register', {
url: '/register',
templateUrl: '/views/register.html',
controller: 'AuthCtrl',
onEnter: [
'$state',
'auth',
function ($state, auth) {
if (auth.isLoggedIn())
$state.go('home')
}
]
})
.state('login', {
url: '/login',
templateUrl: '/views/login.html',
controller: 'AuthCtrl',
onEnter: [
'$state',
'auth',
function ($state, auth) {
if (auth.isLoggedIn())
$state.go('home')
}
]
});
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('home');
}
]);
Моя иерархия папок выглядит так:
meanit
public
js
app.js (Angular)
routes
index.js (Express routes)
views (Angular templates)
index.html
home.html
posts.html
register.html
login.html
server.js
Все маршруты работают по назначению, но когда я перезагружаю страницу на одном из маршрутов или перехожу непосредственно к URL-адресу маршрута (/posts/579d17934b0f5f6b2ff5c72c), я перенаправляюсь сначала в /api/home через Express (предполагается, я думаю), а затем в /home через Угловое вместо маршрута /posts/579d17934b0f5f6b2ff5c72c (НЕ предназначено).
Как заставить навигацию/перезагрузку URL оставаться на подпункте?
(Я посмотрел на AngularJS. Сохраняйте состояние после перезагрузки страницы, но я не понимаю, как настроить парсинг URL/как адаптировать код из принятого ответа в соответствии с моим проектом.)
Кажется, ваша проблема с экспрессом. Ваш catchall делает res.redirect(), который, я думаю, обновляет URL-адрес браузера. Я предлагаю вам просто сделать простой sendfile() или render() вместо redirect().
Маршрут вашего экспресс-сервера должен измениться на:
//This is assuming the index.html file exists on the same directory the server is launched from
router.get('*', function (req, res, next) {
res.render('index', {
title: 'Meanit'
});
});
У меня была аналогичная проблема, когда я начал один из моих проектов angularjs. В моем случае у меня было 2 разных сервера; один для API, а другой предназначен для обслуживания статических файлов. Вот как выглядит мой экспресс-статический сервер:
server.js
//server.js
var express = require('express');
var app = express();
//use very specific paths to the different resource folders
app.use('/js', express.static('public/js'));
app.use('/css', express.static('public/css'));
app.use('/img', express.static('public/img'));
app.use('/views', express.static('public/views'));
app.use('/bower_components', express.static('public/bower_components'));
var port = process.env.PORT || 80;
var staticExtensions = ['css','js','png','gif','jpg','woff','woff2','ttf','map'];
var deeperPaths = ['/posts']; //an array of deeper paths that need special treatment
//cater specifically for post, since it deeper than other paths (relative to the other assets /css, /js etc)
app.get('/posts/:postId', function(req,res){
console.log('fetching matched request: '+ req.path + '...');
res.sendFile(__dirname +'/public/index.html');
});
//any other request returns the index.html file, where angularjs routing takes over
app.get('*', function(req, res) {
console.log('fetching '+ req.path + '...');
var filePath = __dirname +'/public/index.html';
var requestPath = req.path.split('?')[0];
var fileExtension = requestPath.split('.').pop();
//if it a static resource make relative to /public
if(staticExtensions.lastIndexOf(fileExtension)>-1){
deeperPaths.forEach(function(path, index){
//this is not a very reliable test, but it works for now
if(req.path.indexOf(path)===0){
filePath = __dirname + '/public' + req.path.replace(path, '');
}
});
}
res.sendFile(filePath); // load our public/index.html file
});
// START THE SERVER
app.listen(port);
console.log('Website started on port ' + port);
Надеюсь это поможет...