1

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

<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>

引发此错误:

Uncaught TypeError: Cannot call method 'toJSON' of undefined

但是,如果我取出{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;
    }

所以我猜this.model是未定义的。这是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”,当然没有@restaurantLocationsid 为 的成员restuarant_locationsidset set to的事实restaurant_locations有一定的意义;我点击的网址是http://localhost:3000/restaurant_locations. 但它似乎应该调用index函数,而不是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)
4

1 回答 1

0

id设置为"restaurant_locations",当然也没有 of 的成员@restaurantLocationsidof "restuarant_locations"

听起来您有路由问题,所以让我们看看您的路由:

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

我在那里看到了几个问题。首先,路由不是正则表达式,所以".*"不匹配什么/.*/(即任何字符序列),它实际上匹配任意数量的句点(即/^.*$/);您可以自己运行它_routeToRegex,看看会发生什么'.*'

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 + '$');
},

下一个问题是它":id"几乎可以匹配任何东西。routeToRegexp转换":id"/^([^/]+)$/; 该正则表达式匹配任何非空的非斜杠序列,特别是,它将匹配您的大多数其他路线匹配的内容。

因此,当您期望从 击中'.*': 'index'/restaurant_locations,您实际上是在击中':id': 'show',并且您很幸运,'/new'并且'/index'也没有被 匹配':id'。请记住,(Java|Coffee)Script 对象中元素的顺序是实现定义的,因此它们在源代码中出现的顺序实际上并不重要;许多 JavaScript 实现会尊重源代码顺序,但从不依赖它。

由于路由顺序无关紧要,您必须将您的routes键视为一个简单的无序集合,并且您 - 人类 - 必须确保您的路由模式确实匹配不同的事物。如果您确实需要重叠路由模式并且需要它们以特定顺序匹配,那么您可以使用route路由器中的方法以initialize所需的顺序手动添加路由(作为路由模式或正则表达式)。


执行摘要:修复您的路线,使其与不同的事物相匹配。

于 2012-06-27T17:41:09.380 回答