2013-04-29 43 views
3

我在RequireJS/Backbone.js應用程序中遇到HTML5 pushState的問題,我很確定我做錯了什麼,但我無法識別問題,我已經嘗試了幾個小時。pushState阻止來自工作的Backbone.js路線

前言:所有RequireJS依賴關係都位於其正確的文件夾中。

這是我的問題:我有一個基本的小設置 - 我使用的唯一骨幹組件是路由器。在默認的路由中,我在路由器中調用了一個'home'方法。這個方法只不過是提醒「測試」,並且它工作。

但是,一旦我將{pushState: true}作爲參數添加到頂級app.js文件中的Backbone.history.start(),則不再調用'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://協議導航到該實例將不起作用。 (這是我在上述問題中犯的錯誤)。

對於這個簡單的使用情況下,我編寫了,供應一個index.jade視圖(I除去的index.html),當它遇到任何通配符路線,並且然後允許骨幹簡單ExpressJS服務器要正確渲染的代碼這個小片段的路線:

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

然而,正在做進一步的修改,你應該想支持搜索引擎的抓取勢在必行,以及這些變化涉及具有特定的路線 - 服務器 - 邊版本你的服務器可以渲染你的視圖,以防直接訪問路由。如果您不希望支持SEO爬行,例如在需要用戶登錄的Web應用程序的情況下,則通過單個渲染文件重新路由所有路由都可以。 Backbone足夠聰明地檢測剩餘的路徑路徑以呈現適當的視圖。這在the Backbone documentation

注說,使用真實的URL需要你的Web服務器能夠正確顯示這些頁面,因此後端改變是必需的也是如此。例如,如果您的路由爲/ documents/100,則如果瀏覽器直接訪問該URL,則您的Web服務器必須能夠提供該頁面。對於完整的搜索引擎可爬行性,最好讓服務器爲頁面生成完整的HTML ...但如果它是一個Web應用程序,只需渲染與根URL相同的內容,然後用Backbone填充其餘內容視圖和JavaScript工作正常。

注:使用pushState的可以對如何錨標籤(<a href='/route'>)工作的一個暗示,因爲在默認情況下,他們仍然試圖「刷新」頁面來獲取匹配的路由。 Backbone的路由器提供了一個navigate方法,當與click事件處理程序結合使用時,您可以繞過此默認行爲。 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

我遇到了同樣的問題,試圖找出爲什麼我的骨幹學習項目的所有工作,但卓別林的基本樣板沒有。他們在構建路由器時選擇pushState:true。 找出爲什麼這是理想的可能是另外幾個小時的閱讀,但我真的很喜歡所有我的文件在文件中的簡單性:// url沒有任何服務器,特別是當我的代碼需要在諸如PhoneGap – kert 2013-07-04 01:28:51

+0

還沒有在卓別林嘗試,但我相信你可以重寫,不是嗎? – razorbeard 2013-07-04 05:04:10

+0

很容易完成,經過很長一段時間,通過代碼試圖弄清楚發生了什麼。那麼,至少是一次很好的學習練習。 – kert 2013-07-05 07:12:42