多条匹配路线

发布于 2024-10-20 20:30:42 字数 714 浏览 2 评论 0原文

我有一个backbone.js 应用程序,它定义了两个控制器,并且这两个控制器都定义了与location.hash 匹配的路由模式。我无法让它们都启动 - 例如

ManagerController = Backbone.Controller.extend({
   routes: {
      ":name":      "doStuff"
   },

   doStuff : function(name) {
      console.log("doStuff called...");
   }
});

Component1Controller = Backbone.Controller.extend({
   routes: {
      "xyz123":      "doMoreStuff"
   },

   doMoreStuff : function() {
      console.log("doMoreStuff called...");
   }
});

,如果网址是“http://mysite.com/#xyz123”,那么我会看到调用“doStuff()”,或者如果我注释掉该路线,然后调用“doMoreStuff()”。但不是两者兼而有之。

我使用这种架构是因为我的页面是高度面向组件的,并且每个组件都定义了自己的控制器。 “组件管理器”还定义了一个控制器,它对所有路由进行一些内务管理。

我是否应该能够配置两个响应同一路由的控制器?干杯,

科林

I've got a backbone.js application that defines two controllers, and the controllers both define route patterns which match the location.hash. I'm having trouble getting both of them to fire - e.g.

ManagerController = Backbone.Controller.extend({
   routes: {
      ":name":      "doStuff"
   },

   doStuff : function(name) {
      console.log("doStuff called...");
   }
});

Component1Controller = Backbone.Controller.extend({
   routes: {
      "xyz123":      "doMoreStuff"
   },

   doMoreStuff : function() {
      console.log("doMoreStuff called...");
   }
});

so if the url is "http://mysite.com/#xyz123", then I am seeing 'doStuff()' called, or if I comment out that route, then 'doMoreStuff()' is called. But not both.

I'm using this architecture because my page is highly component oriented, and each component defines its own Controller. A 'component manager' also defines a Controller which does some house keeping on all routes.

Should I be able to configure two controllers that both respond to the same route? Cheers,

Colin

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

为你拒绝所有暧昧 2024-10-27 20:30:42

简短的回答:不,你不能那样做。每页一个控制器。

长答案:当您实例化一个新控制器时,它将其路由添加到历史单例中。 History 单例正在监视 URL 的哈希组件,当哈希发生变化时,它会扫描路由以查找符合其需求的第一个表达式。然后它触发与该路由关联的函数(该函数已绑定到声明它的控制器)。它只会发射一次,如果发生冲突,发射的顺序在形式上是不确定的。 (实际上,它可能是确定性的。)

哲学答案:控制器是一个“视图”对象,它根据 URL 的哈希组件影响整个页面的呈现。其目的是提供用户将来可以访问的具有书签功能的 URL,以便当他访问某个 URL 时,他可以从多个视图中预先选择的视图开始。从您的描述来看,听起来您正在操纵这个公开暴露的、可手动寻址的项目来操纵视口的不同部分,同时不干涉其他部分。事情不是这样的。

Backbone 的优点之一是,如果您向它传递一条已经是正则表达式的路由,它会按原样使用它。因此,如果您尝试使用控制器创建可添加书签的布局描述(组件 1 在显示模式“A”下位于右上角,组件 2 在显示模式“B”下位于左上角,等等)我可以建议一些替代方案 - 在 URL 的哈希部分中为每个名称空间分配一个名称空间,并创建忽略其余部分的路由,即

routes: {
    new RegExp('^([^\/]*)/.*

查看第一个如何仅使用第一个斜杠之后的项目,第二个如何使用第二个斜杠之后的项目,等等。你可以完全按照你想要的方式编码你的魔法。

不过,我建议,如果您要对组件的外观和感觉做一些事情,并且您希望其具有相当持久性,那么您可以研究从某些本地存储获取和设置其 cookie 的视图;如果它们足够小,饼干就足够了。

): 'doComponent1stuff', new RegExp('^[^\/]*/([^\/]*)\/.*

查看第一个如何仅使用第一个斜杠之后的项目,第二个如何使用第二个斜杠之后的项目,等等。你可以完全按照你想要的方式编码你的魔法。

不过,我建议,如果您要对组件的外观和感觉做一些事情,并且您希望其具有相当持久性,那么您可以研究从某些本地存储获取和设置其 cookie 的视图;如果它们足够小,饼干就足够了。

: 'doComponent2stuff', }

查看第一个如何仅使用第一个斜杠之后的项目,第二个如何使用第二个斜杠之后的项目,等等。你可以完全按照你想要的方式编码你的魔法。

不过,我建议,如果您要对组件的外观和感觉做一些事情,并且您希望其具有相当持久性,那么您可以研究从某些本地存储获取和设置其 cookie 的视图;如果它们足够小,饼干就足够了。

Short answer: No, you can't do that. One Controller per page.

Long answer: When you instantiate a new Controller, it adds its routes to the History singleton. The History singleton is monitoring the hash component of the URL, and when the hash changes, it scans the routes for the first expression that matches its needs. It then fires the function associated with that route (that function has been bound to the controller in which it was declared). It will only fire once, and if there is a conflict the order in which it fires is formally indeterminate. (In practice it's probably deterministic.)

Philosophical answer: The controller is a "view" object which affects the presentation of the whole page based on the hash component of the URL. Its purpose is to provide bookmark-capable URLs that the user can reach in the future, so that when he goes to a URL he can start from a pre-selected view among many. From your description, it sounds like you're manipulating this publicly exposed, manually addressable item to manipulate different parts of your viewport, while leaving others alone. That's not how it works.

One of the nice things about Backbone is that if you pass it a route that's already a regular expression, it will use it as-is. So if you're trying to use the controller to create a bookmarkable description of the layout (component 1 in the upper right hand corner in display mode "A", component 2 in the upper left corner in display mode "B", etc) I can suggest a number of alternatives-- allocate each one a namespace in the hash part of the URL, and create routes that ignore the rest, i.e.

routes: {
    new RegExp('^([^\/]*)/.*

See how the first uses only items after the first slash, the second after the second slash, etc. You can encode your magic entirely how you want.

I suggest, though, that if you're going to be doing something with the look and feel of the components, and you want that to be reasonably persistent, that you look into the views getting and setting their cookies from some local store; if they're small enough, cookies will be enough.

): 'doComponent1stuff', new RegExp('^[^\/]*/([^\/]*)\/.*

See how the first uses only items after the first slash, the second after the second slash, etc. You can encode your magic entirely how you want.

I suggest, though, that if you're going to be doing something with the look and feel of the components, and you want that to be reasonably persistent, that you look into the views getting and setting their cookies from some local store; if they're small enough, cookies will be enough.

: 'doComponent2stuff', }

See how the first uses only items after the first slash, the second after the second slash, etc. You can encode your magic entirely how you want.

I suggest, though, that if you're going to be doing something with the look and feel of the components, and you want that to be reasonably persistent, that you look into the views getting and setting their cookies from some local store; if they're small enough, cookies will be enough.

や莫失莫忘 2024-10-27 20:30:42

我有一个非常相似的问题。目前,骨干网在第一个匹配路由之后停止。我有一个肮脏的解决方法,我重写了 Backbone History 的 loadUrl 方法。在这里,我迭代所有已注册的路由并触发所有匹配路由的回调。

_.extend(Backbone.History.prototype, {
  loadUrl : function() {
    var fragment = this.fragment = this.getFragment();
    var matched = false;
    _.each(this.handlers, function(handler) {
      if (handler.route.test(fragment)) {
        handler.callback(fragment);
        matched = true;
      }
    });
    return matched;
  }
})

从哲学上讲,我同意每页有一个控制器。然而,在基于组件的视图框架中,如果每个路由有多个视图渲染视图状态的不同部分,那就太好了。

欢迎评论。

I have a very similar issue. At present, backbone stops after the first matching route. I have a dirty workaround where I am overriding the loadUrl method of Backbone History. Here I am iterating through all of the registered routes and triggering callback for all of the matching routes .

_.extend(Backbone.History.prototype, {
  loadUrl : function() {
    var fragment = this.fragment = this.getFragment();
    var matched = false;
    _.each(this.handlers, function(handler) {
      if (handler.route.test(fragment)) {
        handler.callback(fragment);
        matched = true;
      }
    });
    return matched;
  }
})

Philosophically, I am fine with having single controller per page. However, in a component based view framework, it will be nice to have multiple views per route rendering different parts of a view state.

Comments are welcome.

悲念泪 2024-10-27 20:30:42

我已经使用命名空间来处理类似的问题。每个模块都有自己的模块控制器,但仅限于处理以 /moduleName/ 开头的路由,这样模块就可以独立开发。

I've used namespacing to deal with a similar problem. Each module comes with it's own module controller, but is restricted to handle routes that start with /moduleName/ this way modules can be developed independently.

埋葬我深情 2024-10-27 20:30:42

我还没有完全测试这一点,如果你看一下 Backbone.js 源代码,你可以在第 1449 行看到这一点:

// Attempt to load the current URL fragment. If a route succeeds with a
// match, returns `true`. If no defined routes matches the fragment,
// returns `false`.
loadUrl: function(fragment) {
  fragment = this.fragment = this.getFragment(fragment);
  return _.any(this.handlers, function(handler) {
    if (handler.route.test(fragment)) {
      handler.callback(fragment);
      return true;
    }
  });
}

any 方法一旦与处理程序路由匹配(带有“return true”)就会停止,只需注释掉返回,就不会发生短路,并且所有处理程序都会被测试。使用具有两个模块的木偶应用程序对此进行了测试,每个模块都有自己的路由器和控制器,监听相同的路由并同时启动。

I haven't fully tested this yet, if you take a look at the Backbone.js source, you can see this at line 1449:

// Attempt to load the current URL fragment. If a route succeeds with a
// match, returns `true`. If no defined routes matches the fragment,
// returns `false`.
loadUrl: function(fragment) {
  fragment = this.fragment = this.getFragment(fragment);
  return _.any(this.handlers, function(handler) {
    if (handler.route.test(fragment)) {
      handler.callback(fragment);
      return true;
    }
  });
}

The any method will stop as soon as it matches a handler route (with the "return true"), just comment the return and the short-circuit will never happend, and all the handlers will be tested. Tested this with a marionette app with two modules, each one having it's own router and controller, listening same routes anb both fired up.

九八野马 2024-10-27 20:30:42

我认为这是解决路由问题的最简单方法

:{
'': '用户网格',
'用户':'用户网格',
}

I think this is the simplest way of resolving it

routes: {
'': 'userGrid',
'users': 'userGrid',
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文