2013-04-29 2 views
3

У меня проблема с HTML5 pushState в приложении RequireJS/Backbone.js, я уверен, что я делаю что-то неправильно, но я не могу определить проблему, я Я пробовал несколько часов.pushState предотвращает маршруты Backbone.js от работы

Предисловие: все зависимости RequireJS находятся в их правильных папках.

Вот моя проблема: у меня есть базовая небольшая настройка - единственным компонентом Backbone, который я использую, является маршрутизатор. На маршруте по умолчанию «» я вызываю «домашний» метод в маршрутизаторе. Этот метод не более чем предупреждает «Тест», и он работает.

Однако, как только я добавляю {pushState: true} в качестве параметра в Backbone.history.start() в файл верхнего уровня app.js, метод «home» больше не вызывается.

Эти блоки кода, в котором это происходит:

index.html:

<!doctype html> 
<html> 
    <head> 
    <title>Todo</title> 
    <script data-main="assets/js/app/app.js" src="assets/js/app/lib/require.js"></script> 
    </head> 
    <body> 
    <div id="main"></div> 
    </body> 
</html> 

app.js:

require.config({ 
    baseUrl: 'assets/js/app', 
    paths: { 
    'underscore': 'lib/underscore', 
    'jquery': 'lib/jquery', 
    'backbone': 'lib/backbone', 
    'text': 'lib/text', 
    'handlebars': 'lib/handlebars', 
    'router': 'router/router' 
    }, 
    shim: { 
    'underscore': { 
     exports: '_' 
    }, 
    'backbone': { 
     deps: ['underscore', 'jquery'], 
     exports: 'Backbone' 
    } 
    } 
}); 
require(['router', 'backbone'], function(Router, Backbone) { 
    var router = new Router(); 
    Backbone.history.start({ pushState: true }); 
}); 

router.js:

define(['backbone'], function(Backbone) { 
    var Router = Backbone.Router.extend({ 
    routes: { 
     '': 'home' 
    }, 
    home: function() { 
     alert('test'); 
    } 
    }); 
    return Router; 
}); 

Что я делаю неправильно? Это неправильный, запутанный подход?

ответ

1

Я придумал решение своей проблемы, это забавно.

Проблема с внедрением pushState заключается в том, что для любого маршрута для работы, даже для основного маршрута по умолчанию, для первоначального отображения страницы необходим серверный сервер, чтобы затем Backbone мог запустить соответствующий JavaScript после проверки маршрута.

Это означает, что разработка локального экземпляра и переход к нему с использованием протокола file:// не будут работать. (Это то, что я сделал ошибку в этом вопросе).

Для этого простого случая использования, я закодирован на сервере простых ExpressJS, который служит в index.jade вида (я удалил index.html), когда он встречает любогоподстановочных маршрута, а затем позволяет Backbone для корректного отображения маршрутов с этим крошечным фрагментом кода:

app.get('*', function(req, res) { 
    res.render('index'); 
} 

Однако необходимо, что дальнейшие изменения сделаны, если вы хотите поддержать ползание поисковой системы, и эти изменения включают имеющие маршрутный специфические поддерживаемый сервер сторона versio ns ваших просмотров, которые ваш сервер может отобразить в случае, если маршрут напрямую доступен. Если вы не хотите поддерживать сканирование с помощью SEO, например, в случае веб-приложения, которое требует, чтобы пользователи вошли в систему, а затем повторная маршрутизация все маршрутов через один обработанный файл в порядке. Магистраль достаточно умен, чтобы определить оставшиеся пути маршрута, чтобы отобразить соответствующий вид. Об этом говорится в the Backbone documentation

Обратите внимание, что с использованием реальных URL-адресов требует вашего веб-сервера, чтобы иметь возможность корректно отображать эти страницы, так фонами изменения необходимы, а также. Например, если у вас есть маршрут/documents/100, ваш веб-сервер должен иметь возможность обслуживать эту страницу, если браузер сразу посещает этот URL.Для полной полнотекстовой поисковой системы лучше всего, чтобы сервер сгенерировал полный HTML-код для страницы ... но если это веб-приложение, просто отображая тот же контент, который у вас будет для корневого URL-адреса, и заполняйте остальные с помощью Backbone Представления и JavaScript отлично работают.

ПРИМЕЧАНИЕ: Использование PushState может иметь последствия как якорь метки (<a href='/route'>) работы, по умолчанию, они все равно будут пытаться «обновить» страницу, чтобы принести маршрут согласования. Маршрутизатор Backbone's предлагает метод navigate, который в сочетании с обработчиком событий щелчка позволяет обойти это поведение по умолчанию. shioyama опубликовал пример такого обработчика события в качестве ответа на this question.

ПОЛНЫХ изменений коды:

/app.js

var 
express = require('express'), 
app = express(); 

app.configure(function() { 
    app.set('views', __dirname + '/views'); 
    app.set('view engine', 'jade'); 
    app.use(express.static(__dirname + '/assets')); 
    app.use(app.router); 
    app.locals.pretty = true; 
}); 

app.get('*', function(req, res) { 
    res.render('index'); 
}); 

app.listen(3030, function() { 
    console.log("Listening on 3030"); 
}); 

/активы/JS/приложение/приложение .js

require.config({ 
    baseUrl: '/js/app', 
    paths: { 
    'underscore': 'lib/underscore', 
    'jquery': 'lib/jquery', 
    'backbone': 'lib/backbone', 
    'text': 'lib/text', 
    'handlebars': 'lib/handlebars', 
    'router': 'router/router' 
    }, 
    shim: { 
    'underscore': { 
     exports: '_' 
    }, 
    'backbone': { 
     deps: ['underscore', 'jquery'], 
     exports: 'Backbone' 
    } 
    } 
}); 
require(['router', 'backbone'], function(Router, Backbone) { 
    var router = new Router(); 
    Backbone.history.start({pushState: true}); 
}); 

/assets/js/app/router/router.js

define(['backbone', 'jquery'], function(Backbone, $) { 
    var Router = Backbone.Router.extend({ 
    routes: { 
     '': 'home', 
     'fred': 'fred' 
    }, 
    home: function() { 
     $('#main').append('<p>This is the <strong>HOME</strong> route.'); 
    }, 
    fred: function() { 
     $('#main').append('<p>This is the <strong>FRED</strong> route.'); 
    } 
    }); 
    return Router; 
}); 

/views/index.jade

!!! 
html 
    head 
    title Todo 
    script(data-main='/js/app/app.js', src='/js/app/lib/require.js') 
    body 
    #main 
+0

Я столкнулся с той же проблемой, пытаясь понять, почему мой Backbone обучающих проектов все работа, но основной шаблон от Чаплина не сделал. Они выбирают pushState: true, когда они создают маршрутизатор. Выяснить, почему это желательно, возможно, еще пару часов чтения, но мне очень нравится простота наличия всех моих файлов в файле: // url без какого-либо сервера, особенно когда мой код должен быть переносимым в таких вещах, как PhoneGap – kert

+0

Еще не пробовал в Чаплине, но я уверен, что вы могли бы переодеться, не так ли? – razorbeard

+0

Да, легко сделать, ПОСЛЕ долгое время, пробирая код, пытаясь понять, что происходит. Ну, по крайней мере, хорошее учебное упражнение. – kert

Смежные вопросы