使用Ember.js实现Hashbang URLs

15

我正在尝试设置我的路由器使用“hashbang”URL(#!)。

我尝试过这个,但显然它不起作用:

App.Router.map(function() {
    this.route("index", { path: "!/" });
    this.route("otherState", { path: "!/otherState" });
});

在Ember中能做到这个吗?


我通过覆盖Ember.HashLocation属性并向多个字符串添加一些“!”来使其正常工作。我不确定这是否会导致任何问题。如果没有更好的方法,我将把我的代码作为答案添加。 - twiz
2个回答

19
泰迪·兹尼的回答大部分正确,而registerImplementation似乎是实现这一点的一种清晰方式。我试图编辑他的答案以完全回答该问题,但我的编辑被拒绝了。
无论如何,以下是使Ember使用哈希符号URL的完整代码:
(function() {

var get = Ember.get, set = Ember.set;

Ember.Location.registerImplementation('hashbang', Ember.HashLocation.extend({ 

    getURL: function() {
        return get(this, 'location').hash.substr(2);
    },

    setURL: function(path) {
        get(this, 'location').hash = "!"+path;
        set(this, 'lastSetURL', "!"+path);
    },

    onUpdateURL: function(callback) {
        var self = this;
        var guid = Ember.guidFor(this);

        Ember.$(window).bind('hashchange.ember-location-'+guid, function() {
                Ember.run(function() {
                    var path = location.hash.substr(2);
                    if (get(self, 'lastSetURL') === path) { return; }

                    set(self, 'lastSetURL', null);

                    callback(location.hash.substr(2));
                });
        });
    },

    formatURL: function(url) {
        return '#!'+url;
    }

}));

})();

创建应用程序后,您需要更改路由器以利用“hashbang”位置实现:

App.Router.reopen({
    location: 'hashbang'
})

2
很好,只有几个评论:
  • 最好重新打开 App.Router 而不是 Ember.Router(这样您可以保持 Ember 默认设置的清洁,特别是在测试时)
  • 由于您正在扩展 HashLocation,因此不需要覆盖 initwillDestroy,这些函数将被继承,代码会更简单。
- Teddy Zeenny
谢谢。我已经按照你说的进行了更改。 - twiz
2
这个方法完美地工作,但在最后一个Ember中会抛出一个弃用的消息;我们该怎么做才能使用它而不使用弃用的代码? - Cereal Killer
1
以防有人不知道,谷歌也可以爬取使用HTML5 pushState而非hash-bang方法的网站。这是官方的说法:https://www.youtube.com/watch?v=yiAF9VdvRPw这里是Ember文档关于如何使用它的链接:http://emberjs.com/api/classes/Ember.Location.html#toc_historylocation - twiz

10

扩展Ember.HashLocation将是正确的方法。

为了实现清晰干净,您可以执行以下操作。

Ember.Location.registerImplementation('hashbang', Ember.HashLocation.extend({
  // overwrite what you need, for example:
  formatURL: function(url) {
    return '#!' + url;
  }
  // you'll also need to overwrite setURL, getURL, onUpdateURL...
})

然后指示您的应用路由使用您自定义的位置管理实现:

App.Router.reopen({
  location: 'hashbang'
})

好的回答。我在我的解决方案中没有使用registerImplementation。这绝对使它更清晰。我编辑了你的答案,包括完整的代码,以使其工作,因为除了formatURL中的更改之外,还必须进行其他几个更改。 - twiz
由于某些原因,我对您的答案所做的编辑被拒绝了。不确定是怎么回事。无论如何,我刚刚发布了自己的答案,并附上了完全实现哈希URL功能的代码。 - twiz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接