在pushState单页面应用程序中使用URL片段(#)作为模态视图

Dan*_*mov 6 javascript url-routing backbone.js pushstate single-page-application

我们使用Backbone.Router的是仅限pushstate模式,因此我们所有的客户端路由都是无哈希的.
但是,我们在应用程序中实现模态视图时遇到了困难.

挑战如下:

  • 我们想要Back按钮来隐藏当前的模态视图(所以我们需要它有一个URL);
  • 我们希望转发再次显示它而不重绘整个应用程序;
  • 我们希望能够在任何现有路线上"而不仅仅在一个页面上"显示模态;
  • 我们希望能够创建立即显示特定模式的链接(例如登录模式视图).

换句话说,我们希望模态视图在历史中表示.

我们的第一次尝试是使用URL /login作为登录模式,并在route处理程序中专门处理它们.当我们打开时/otherpage,打开模态将导航到/login,并且,当模态关闭时,再次导航到/otherpage.

但是,这有一个非常大的问题:URL /login不会"知道"它应该绘制哪个视图,因此我们必须在按Back和Forward时重绘所有内容.

这实际上是有道理的:主屏幕上的登录模式应该具有与其他页面上的登录模式不同的URL.

我的第二个想法是,也许我们可以使用哈希来指示当前的模态视图:

/
/#login
/otherpage
/otherpage#login
Run Code Online (Sandbox Code Playgroud)

这使得路由处理程序变得简单:

  • 首先,根据匹配的路线绘制实际视图,就像我们之前做的那样.
  • 之后,如果存在哈希,则在顶部显示模态视图.

这也符合哈希是可见文档的"片段"的想法.(是的,应用程序不是文档,bla bla bla.我们仍然希望它们可以被寻址.)

这种方法有任何固有的问题吗?
有没有更好的方法来满足我们的条件?

kin*_*uta 2

如果我正确理解你的问题,我不相信你需要哈希,我相信你可以通过简单地添加更多路由来实现模式。如果您需要支持其他现有路由的登录模式,只需添加另一个将登录添加到末尾的路由即可。这是一个例子:

var Login = Backbone.Model.extend({
    closeLogin: function () {
        this.set({ open: false }, { silent: true });
        this.trigger('loginClosed');
    }
});

var LoginView = Backbone.View.extend({
    el: '#loginModal',     
    initialize: function () {
        this.listenTo(this.model, 'loginClosed', this.closeLogin);
    },
    closeLogin: function () {
        // do whatever you would normally do to close the modal
    }
});

var Router = Backbone.Router.extend({
    routes: {
        '/login': 'defaultRouteLogin',
        '': 'defaultRoute',
        'otherpage/login': 'otherPageRouteLogin',
        'otherpage': 'otherPageRoute'
    },
    defaultRoute: function () {
        // defaultRoute behaviors
        this.login.closeLogin();
    },
    defaultRouteLogin: function () {
        // defaultRoute behavior
        // instantiate login modal
    },
    otherPageRoute: function () {
        // otherPageRoute behavior
        this.login.closeLogin();
    },
    otherPageRouteLogin: function () {
        // otherPageRoute behavior
        // instantiate login modal
    },
    initialize: function () {
        this.login = new Login();
        this.loginView = new LoginView({ model: this.login });
    }
});
Run Code Online (Sandbox Code Playgroud)

为了支持后退按钮行为,请使用一种方法,在可以打开模态框的每个路径上关闭登录模态框。请务必正确排序路线。