使用主干和快速手柄启用pushState而不使用哈希

时间:2015-05-06 22:02:55

标签: backbone.js express handlebars.js

我正在使用https://github.com/shorttompkins/benm,我想在不使用哈希的情况下实现pushState。我已经设定了:

Backbone.history.start({pushState: true});

这是我的server.js:

var express = require('express'),
    http = require('http'),
    path = require('path'),
    routes = require('./app/routes'),
    exphbs = require('express-handlebars'),
    mongoose = require('mongoose'),
    seeder = require('./app/seeder'),
    app = express(),
    bodyParser = require('body-parser'),
    morgan = require('morgan'),
    methodOverride = require('method-override'),
    errorHandler = require('errorhandler');

app.set('port', process.env.PORT || 3300);
app.set('views', __dirname + '/views');
app.engine('handlebars', exphbs({
    defaultLayout: 'main',
    layoutsDir: app.get('views') + '/layouts'
}));
app.set('view engine', 'handlebars');

app.use(morgan('dev'));
app.use(bodyParser());
app.use(methodOverride());

routes.initialize(app, new express.Router());

// static asset routes
app.use('/', express.static(path.join(__dirname, 'public')));
app.use('/bower_components', express.static(path.join(__dirname, 'bower_components')));

// development only
if ('development' === app.get('env')) {
    app.use(errorHandler());
}

//connect to the db server:
mongoose.connect('mongodb://localhost/MyApp');
mongoose.connection.on('open', function() {
    console.log('Connected to Mongoose.');

    // check if the db is empty, if so seed it with some contacts:
    seeder.check();
});

//routes list:
routes.initialize(app);

//finally boot up the server:
http.createServer(app).listen(app.get('port'), function() {
    console.log('Server up: http://localhost:' + app.get('port'));
});

我的routes.js:

var home = require('../controllers/home'),
contacts = require('../controllers/contacts');

module.exports.initialize = function(app) {
    app.get('/', home.index);
    app.get('/api/contacts', contacts.index);
    app.get('/api/contacts/:id', contacts.getById);
    app.post('/api/contacts', contacts.add);
    app.delete('/api/contacts/:id', contacts.delete);
};

这很好用,直到我尝试使用骨干路径刷新页面,例如。 http://localhost:3300/add然后找不到路线,我收到错误'无法获取/添加'。

从我读过的内容中,我需要添加类似于:

的全能路线
app.get('*', function(req, res){
    // serve home page
});

但我无法解决如何使用快速把手来做这件事。

我尝试过的所有东西似乎都停止了服务的静态内容,即使我在server.js中有express.static路由

任何帮助都会非常感激。

1 个答案:

答案 0 :(得分:0)

使用pushstate时,浏览器不会通过pushState()请求添加的URL,但在重新加载页面或重新启动该位置的useragent时可能会这样做。

来自Mozilla开发者网络:

  
      
  • URL - 此参数给出了新历史记录条目的URL。请注意,浏览器在调用pushState()后不会尝试加载此URL,但可能会稍后尝试加载URL,例如在用户重新启动浏览器之后。 [...]
  •   

https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history#The_pushState%28%29_method

这适用于所有用户代理。

pushstate的想法是,在不请求该文档的情况下存储URL的状态对象。但是,如果在上一个浏览会话被销毁后请求用户代理加载该URL,则服务器需要能够提供该URL。请注意,用户也可以通过电子邮件将URL加入书签或发送给其他人。

您的服务器和客户端应该能够初始化符合该URL的应用程序状态。

既然你说过,

  

更喜欢使用标准网址并保留哈希,以便深入查看内容,例如标签,ID等。

您最好的选择似乎是在后端实现路由。所有路线"生成"在你的前端应该服务。您需要为任何这些网址提供单页应用程序文档。

如果你的应用程序应该在正确的位置初始化/启动,你需要

  1. 将当前状态信息从后端传递到客户端应用程序
  2. 从客户端启动应用程序的URL恢复状态
  3. 鉴于当前路线/contacts/24552

    对于选项1:您可以,例如,处理路线,收集24552的联系人数据,并提供内联联系人数据的单页应用程序文档。

    对于选项2:您可以按原样提供单页应用程序文档(API路径除外),检查URL客户端并执行请求客户端。例如,您可以解析location.pathname,提取相关信息(例如"联系人"和ID),并直接调用路由处理程序或导航到未处理的路由并返回到路由{{1触发路由处理程序。

    注意:在内容中使用锚点时,您也可以使用基于哈希的URL。您可以生成这些锚名称(ID)并使用当前应用程序状态路由作为前缀。您的Backbone路由处理程序必须忽略这些锚名称。