Javascript 重写.fetch()可以处理假数据、urlRoot错误和实际模型ajax请求
我很困惑——我以为我的模型绑定工作正常,但它只是作为一个JSFIDLE和伪造的ajax请求。我已经将一个模型绑定到一个视图,如果我重写Javascript 重写.fetch()可以处理假数据、urlRoot错误和实际模型ajax请求,javascript,model-view-controller,backbone.js,coffeescript,marionette,Javascript,Model View Controller,Backbone.js,Coffeescript,Marionette,我很困惑——我以为我的模型绑定工作正常,但它只是作为一个JSFIDLE和伪造的ajax请求。我已经将一个模型绑定到一个视图,如果我重写.fetch()并伪造响应,一切都会正常工作(我可以在页面上更新模型和视图)。但是,当我不重写.fetch()并使用urlRoot参数并等待响应时,就会出现错误 以下是正在工作的JSFIDLE,其中模型在调用.fetch()并使用伪造响应后呈现,而不是更改: 因此,如果我在服务器端有一个API调用: /thing/:id 通过对/thing/1的示例响应: {"
.fetch()
并伪造响应,一切都会正常工作(我可以在页面上更新模型和视图)。但是,当我不重写.fetch()
并使用urlRoot
参数并等待响应时,就会出现错误
以下是正在工作的JSFIDLE,其中模型在调用.fetch()
并使用伪造响应后呈现,而不是更改:
因此,如果我在服务器端有一个API调用:
/thing/:id
通过对/thing/1
的示例响应:
{"id":"1","latitude":"lat1","longitude":"lon1"}
如果我注释掉.fetch()
,就会得到控制台错误:
load js core functions core.js:2
init model timeout app.js:114
initializer callback for history, routes app.js:95
App.Layouts.MyLayout onShow app.js:41
App.Regions.MyRegion onShow app.js:25
App.Models.Thing init app.js:55
App.ItemViews.Thing init app.js:87
Uncaught TypeError: Object #<Object> has no method 'toJSON' backbone.marionette-0.8.1.min.js:9
Parsing App.Models.Thing.fetch() response: {"id":"1","latitude":"lat1","longitude":"lon1"} app.js:62
Thing: {"id":"1","latitude":"lat1","longitude":"lon1"} app.js:66
a Thing has changed, update ItemView! app.js:57
Uncaught TypeError: Cannot call method 'render' of undefined app.js:58
update model app.js:108
Uncaught TypeError: Object #<Object> has no method 'set'
这里发生了很多奇怪和混乱的事情。不要害怕,一切还没有失去,混乱可以解决 主干网应该返回一个
jqXHR
,而不是模型本身。您的fetch
实现错误地返回了@parse resp
,并且返回了@
(这也是不正确的,有时两个错误就是正确的)。结果是:
App.Data.thing = new App.Models.Thing(id: 1).fetch()
当您使用fetch
时,会为您提供一个有用的App.Data.thing
,但主干fetch
不适用。因此,您的fetch
已损坏,并且您没有正确使用fetch
;然后尝试将jqXHR
作为模型提供给视图,视图在jqXHR
而不是模型上设置@view
:
initialize: (options) ->
#...
@options.model.view = @
initialize: (options) ->
@model.on('change', @render)
因此,您在jqXHR
上得到了一个view
属性,但是模型没有@view
(因为App.Data.thing
不是模型),并且您在模型的更改处理程序中得到了一个“无法调用未定义的“render”方法”错误
您应该这样做:
App.Data.thing = new App.Models.Thing(id: 1)
App.Data.thing.fetch()
现在转到您的分析
:
parse: (resp) ->
console.log 'Parsing App.Models.Thing.fetch() response: ' + JSON.stringify resp
@attributes.id = resp.id
@attributes.latitude = resp.latitude
@attributes.longitude = resp.longitude
console.log 'Thing: ' + JSON.stringify @
@
从:
每当服务器在fetch和save中返回模型数据时,都会调用parse。函数被传递给原始响应
对象,并应返回要在模型上设置的属性散列
因此,parse
应该只是将服务器的响应传递到模型上。您的parse
正在设置属性并返回@
。结果是,您最终将执行与m.set(m)
等效的操作。所以,摆脱你的parse
实现,你的实现是不正确的,你甚至不需要它
您的模型/视图连接是反向的:视图引用模型,模型不引用视图。您的模型中包含以下内容:
initialize: (item) ->
console.log 'App.Models.Thing init'
@bind 'change', ->
console.log 'a Thing has changed, update ItemView!'
@view.render()
在你看来:
initialize: (options) ->
console.log 'App.ItemViews.Thing init'
# Bind
@options.model.view = @
您应该在创建模型时将模型传递给视图(您可以这样做,这样就可以了):
然后视图应绑定到模型:
initialize: (options) ->
#...
@options.model.view = @
initialize: (options) ->
@model.on('change', @render)
您可以在模型中删除初始化实现
此外,您可以(也应该)直接在命名空间中声明类,但不要这样做:
class Thing extends Backbone.Marionette.ItemView
#...
App.ItemViews.Thing = Thing
setTimeout 'App.updateModel()', 2000
这样做:
class App.ItemViews.Thing extends Backbone.Marionette.ItemView
#...
setTimeout (-> App.updateModel()), 2000
此外,几乎不应该使用is-evil的string/eval形式。不要这样做:
class Thing extends Backbone.Marionette.ItemView
#...
App.ItemViews.Thing = Thing
setTimeout 'App.updateModel()', 2000
这样做:
class App.ItemViews.Thing extends Backbone.Marionette.ItemView
#...
setTimeout (-> App.updateModel()), 2000
可能还有更多,但希望这能让你开始并解决眼前的问题。这里发生了很多奇怪和困惑的事情。不要害怕,一切还没有失去,混乱可以解决
主干网应该返回一个jqXHR
,而不是模型本身。您的fetch
实现错误地返回了@parse resp
,并且返回了@
(这也是不正确的,有时两个错误就是正确的)。结果是:
App.Data.thing = new App.Models.Thing(id: 1).fetch()
当您使用fetch
时,会为您提供一个有用的App.Data.thing
,但主干fetch
不适用。因此,您的fetch
已损坏,并且您没有正确使用fetch
;然后尝试将jqXHR
作为模型提供给视图,视图在jqXHR
而不是模型上设置@view
:
initialize: (options) ->
#...
@options.model.view = @
initialize: (options) ->
@model.on('change', @render)
因此,您在jqXHR
上得到了一个view
属性,但是模型没有@view
(因为App.Data.thing
不是模型),并且您在模型的更改处理程序中得到了一个“无法调用未定义的“render”方法”错误
您应该这样做:
App.Data.thing = new App.Models.Thing(id: 1)
App.Data.thing.fetch()
现在转到您的分析
:
parse: (resp) ->
console.log 'Parsing App.Models.Thing.fetch() response: ' + JSON.stringify resp
@attributes.id = resp.id
@attributes.latitude = resp.latitude
@attributes.longitude = resp.longitude
console.log 'Thing: ' + JSON.stringify @
@
从:
每当服务器在fetch和save中返回模型数据时,都会调用parse。函数被传递给原始响应
对象,并应返回要在模型上设置的属性散列
因此,parse
应该只是将服务器的响应传递到模型上。您的parse
正在设置属性并返回@
。结果是,您最终将执行与m.set(m)
等效的操作。所以,摆脱你的parse
实现,你的实现是不正确的,你甚至不需要它
您的模型/视图连接是反向的:视图引用模型,模型不引用视图。您的模型中包含以下内容:
initialize: (item) ->
console.log 'App.Models.Thing init'
@bind 'change', ->
console.log 'a Thing has changed, update ItemView!'
@view.render()
在你看来:
initialize: (options) ->
console.log 'App.ItemViews.Thing init'
# Bind
@options.model.view = @
您应该在创建模型时将模型传递给视图(您可以这样做,这样就可以了):
然后视图应绑定到模型:
initialize: (options) ->
#...
@options.model.view = @
initialize: (options) ->
@model.on('change', @render)
您可以在模型中删除初始化实现
此外,您可以(也应该)直接在命名空间中声明类,但不要这样做:
class Thing extends Backbone.Marionette.ItemView
#...
App.ItemViews.Thing = Thing
setTimeout 'App.updateModel()', 2000
这样做:
class App.ItemViews.Thing extends Backbone.Marionette.ItemView
#...
setTimeout (-> App.updateModel()), 2000
此外,几乎不应该使用is-evil的string/eval形式。不要这样做:
class Thing extends Backbone.Marionette.ItemView
#...
App.ItemViews.Thing = Thing
setTimeout 'App.updateModel()', 2000
这样做:
class App.ItemViews.Thing extends Backbone.Marionette.ItemView
#...
setTimeout (-> App.updateModel()), 2000
可能还有更多,但希望这能让你开始并解决眼前的问题。有用、措辞恰当、有趣。谢谢乐于助人,措辞得体,f