Backbone.js 主干视图的模型缺失,但我不明白为什么

Backbone.js 主干视图的模型缺失,但我不明白为什么,backbone.js,Backbone.js,我有一个简单但令人困惑的问题。我有以下代码: <div id="restaurant_locations"></div> <script type="text/javascript"> $(function() { window.router = new Lunchhub.Routers.RestaurantLocationsRouter({ restaurantLocations: <%= @restaurant_locati

我有一个简单但令人困惑的问题。我有以下代码:

<div id="restaurant_locations"></div>

<script type="text/javascript">
  $(function() {
    window.router = new Lunchhub.Routers.RestaurantLocationsRouter({
      restaurantLocations: <%= @restaurant_locations.to_json.html_safe -%>
    });
    Backbone.history.start({pushState: true});
  });
</script>
但是,如果我去掉{pushState:true}部分,只做Backbone.history.start而不使用任何参数,它就可以正常工作

错误旁边显示show_view.js:19。下面是show_view.js的这部分内容:

    ShowView.prototype.template = JST["backbone/templates/restaurant_locations/show"];

    ShowView.prototype.render = function() {
      $(this.el).html(this.template(this.model.toJSON())); // LINE 19
      Uncaught TypeError: Cannot call method 'toJSON' of undefined
      return this;
    }
所以我猜这个模型是未定义的。以下是show_view咖啡脚本:

Lunchhub.Views.RestaurantLocations ||= {}

class Lunchhub.Views.RestaurantLocations.ShowView extends Backbone.View
  template: JST["backbone/templates/restaurant_locations/show"]

  render: ->
    $(@el).html(@template(@model.toJSON() ))
    return this
如果我能让@model成为它需要的样子,我想它可能会解决这个问题。但我不知道@model是从哪里来的

我需要做什么

编辑:我还有一点。在下面的show函数中,id设置为restaurant_locations,当然@restaurantLocations中没有id为restaurant_locations的成员。事实上,将id设置为餐厅位置是有一定意义的;我点击的网址是http://localhost:3000/restaurant_locations. 但它似乎应该调用索引函数,而不是show,如果我要访问的是这个URL的话

class Lunchhub.Routers.RestaurantLocationsRouter extends Backbone.Router
  initialize: (options) ->
    @restaurantLocations = new Lunchhub.Collections.RestaurantLocationsCollection()
    @restaurantLocations.reset options.restaurantLocations

  routes:
    "new"      : "newRestaurantLocation"
    "index"    : "index"
    ":id/edit" : "edit"
    ":id"      : "show"
    ".*"        : "index"

  newRestaurantLocation: ->
    @view = new Lunchhub.Views.RestaurantLocations.NewView(collection: @restaurantLocations)
    $("#restaurant_locations").html(@view.render().el)

  index: ->
    @view = new Lunchhub.Views.RestaurantLocations.IndexView(restaurantLocations: @restaurantLocations)
    $("#restaurant_locations").html(@view.render().el)

  show: (id) ->
    restaurant_location = @restaurantLocations.get(id)

    @view = new Lunchhub.Views.RestaurantLocations.ShowView(model: restaurant_location)
    $("#restaurant_locations").html(@view.render().el)

  edit: (id) ->                   
    restaurant_location = @restaurantLocations.get(id)

    @view = new Lunchhub.Views.RestaurantLocations.EditView(model: restaurant_location)
    $("#restaurant_locations").html(@view.render().el)
id设置为restaurant_locations,当然@restaurantLocations中没有id为restaurant_locations的成员

听起来你的路线有问题,让我们看看你的路线:

routes:
  "new"      : "newRestaurantLocation"
  "index"    : "index"
  ":id/edit" : "edit"
  ":id"      : "show"
  ".*"       : "index"
我发现有几个问题。首先,路由不是正则表达式,因此。*与/*/不匹配,即任何字符序列,它实际上匹配任何数量的句点,即/^.*$/;您可以自己运行它以查看“.”发生了什么:

下一个问题是:id几乎匹配任何东西。routeToRegexp将:id转换为/^[^/]+$/;该正则表达式匹配任何非空的非斜杠序列,尤其是与大多数其他路由匹配的序列

因此,当您希望从/restaurant_locations中点击“.*”:“index”时,您实际上是在点击“:id”:“show”,幸运的是“/new”和“/index”也没有与“:id”匹配。请记住,Java | CoffeeScript对象中元素的顺序是由实现定义的,因此它们在源代码中出现的顺序实际上并不重要;许多JavaScript实现将尊重源代码顺序,但从不依赖它

由于路由顺序无关紧要,您必须将路由密钥视为一个简单的无序集,并且您必须确保您的路由模式确实匹配不同的内容。如果您确实需要重叠的路由模式,并且需要它们以特定的顺序匹配,那么您可以使用路由器中的方法以所需的顺序手动将路由添加为路由模式或正则表达式


执行摘要:修复您的路由,使其与不同的内容相匹配。

showVideo.model来自新的ShowView{model:myModelInstance}。抱歉,但我必须说,如果您不知道应该在更简单的场景中开始使用主干进行研究。也许我应该提到:我在Rails上,使用主干Rails gem,它会自动生成大量代码。我希望它可以工作,而不必调试生成的代码,但事实并非如此。此外,我发现了令人不快的一行:@view=new-午餐中心.Views.RestaurantLocations.ShowViewmodel:restaurant\u位置。在这种情况下,餐厅位置未定义,这显然是行不通的。现在的问题是为什么变量被设置为错误的东西。我将在稍后发布相关代码。谢谢。我能够解决这个问题,也就是说,通过在顶部添加一个新的路由:index:restaurant\u locations,使页面加载无误。看起来路线顺序确实很重要,因为在底部添加新路线没有任何作用,但在顶部添加新路线却起了作用。@Jasonswitt:根据源代码中的路线顺序,这是一场赌博,绝对不能保证它会起作用。根据源代码顺序,您将自己置于浏览器相关bug的环境中。JavaScript标准不能保证迭代对象的键会按源代码顺序生成键。
routes:
  "new"      : "newRestaurantLocation"
  "index"    : "index"
  ":id/edit" : "edit"
  ":id"      : "show"
  ".*"       : "index"
var namedParam    = /:\w+/g;
var splatParam    = /\*\w+/g;
var escapeRegExp  = /[-[\]{}()+?.,\\^$|#\s]/g;
//...
_routeToRegExp: function(route) {
  route = route.replace(escapeRegExp, '\\$&')
               .replace(namedParam, '([^\/]+)')
               .replace(splatParam, '(.*?)');
  return new RegExp('^' + route + '$');
},