0 javascript model-view-controller coffeescript backbone.js marionette
我很困惑 - 我以为我的模型绑定工作正常,但它只是作为一个伪造的ajax请求的jsFiddle.我已将模型绑定到视图,如果我覆盖.fetch()
并伪造响应,则一切正常(我可以更新模型和页面上的视图更新).但是,当我不覆盖.fetch()
并使用urlRoot
param并等待响应时,我会收到错误.
这是工作的jsFiddle,其中模型在.fetch()
使用伪造的响应调用后呈现,而不是更改:
http://jsfiddle.net/franklovecchio/FkNwG/182/
所以如果我在服务器端有一个API调用:
/thing/:id
通过示例响应/thing/1
:
{"id":"1","latitude":"lat1","longitude":"lon1"}
Run Code Online (Sandbox Code Playgroud)
我注释掉了.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'
Run Code Online (Sandbox Code Playgroud)
.fetch()
注释掉的代码:
window.App = { }
window.App.Regions = { }
window.App.Layouts = { }
window.App.Models = { }
window.App.ItemViews = { }
window.App.Rendered = { }
window.App.Data = { }
# ----------------------------------------------------------------
# App.Regions.MyRegion
# ----------------------------------------------------------------
class MyRegion extends Backbone.Marionette.Region
el: '#myregion'
onShow: (view) ->
console.log 'App.Regions.MyRegion onShow'
App.Regions.MyRegion = MyRegion
# ----------------------------------------------------------------
# App.Layouts.MyLayout
# ----------------------------------------------------------------
class MyLayout extends Backbone.Marionette.Layout
template: '#template-mylayout'
regions:
contentRegion: '#content'
anotherRegion: '#another'
onShow: (view) ->
console.log 'App.Layouts.MyLayout onShow'
App.Layouts.MyLayout = MyLayout
# ----------------------------------------------------------------
# App.Models.Thing
# ----------------------------------------------------------------
class Thing extends Backbone.Model
urlRoot: () ->
'/thing'
initialize: (item) ->
console.log 'App.Models.Thing init'
@bind 'change', ->
console.log 'a Thing has changed, update ItemView!'
@view.render()
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 @
@
# If I don't override, I get an error.
###fetch: () ->
console.log 'override ajax for test - App.Models.Thing.fetch()'
resp =
id: 1
latitude: 'lat1'
longitude: 'lon1'
console.log 'Faked Thing response: ' + JSON.stringify resp
@parse resp###
App.Models.Thing = Thing
# ----------------------------------------------------------------
# App.ItemViews.Thing
# ----------------------------------------------------------------
class Thing extends Backbone.Marionette.ItemView
template: '#template-thing'
initialize: (options) ->
console.log 'App.ItemViews.Thing init'
# Bind
@options.model.view = @
App.ItemViews.Thing = Thing
# ----------------------------------------------------------------
# App.MyApp ...the Marionette application
# ----------------------------------------------------------------
App.MyApp = new Backbone.Marionette.Application()
# ----------------------------------------------------------------
# App.MyApp before init
# ----------------------------------------------------------------
App.MyApp.addInitializer (data) ->
console.log 'initializer callback for history, routes'
App.Rendered.myRegion = new App.Regions.MyRegion
App.Rendered.myLayout = new App.Layouts.MyLayout
App.Rendered.myRegion.show App.Rendered.myLayout
# GET thing
App.Data.thing = new App.Models.Thing(id: 1)
.fetch()
App.Rendered.thingView = new App.ItemViews.Thing(model: App.Data.thing)
App.Rendered.myLayout.contentRegion.show App.Rendered.thingView
# ----------------------------------------------------------------
# Test
# ----------------------------------------------------------------
App.updateModel = ->
console.log 'update model'
# Update the Thing with id = 1
App.Data.thing.set
latitude: 'somenewlat'
App.updateModelTimeout = ->
console.log 'init model timeout'
setTimeout 'App.updateModel()', 2000
App.updateModelTimeout()
$ ->
data = { }
App.MyApp.start data
?
Run Code Online (Sandbox Code Playgroud)
这里有很多奇怪而混乱的事情.不要害怕,一切都还没有丢失,混乱可以解决.
Backbone fetch
应该返回一个jqXHR
,而不是模型本身.您的fetch
实现错误地返回@parse resp
并parse
返回@
(这也是错误的,有时两个错误确实是正确的).结果就是:
App.Data.thing = new App.Models.Thing(id: 1).fetch()
Run Code Online (Sandbox Code Playgroud)
App.Data.thing
当你使用你的时候会给你一个有用的东西,fetch
但是对于Backbone来说它是不对的fetch
.所以你fetch
的破坏了,你没有fetch
正确使用; 那么你试着把jqXHR
你的视图作为模型,你的视图设置@view
在jqXHR
而不是模型上:
initialize: (options) ->
#...
@options.model.view = @
Run Code Online (Sandbox Code Playgroud)
所以你最终得到了一个view
属性,jqXHR
但模型没有@view
(因为App.Data.thing
不是模型),你得到一个"无法调用方法'渲染'未定义"错误在你的模型的变更处理程序中.
你应该这样做:
App.Data.thing = new App.Models.Thing(id: 1)
App.Data.thing.fetch()
Run Code Online (Sandbox Code Playgroud)
现在你的parse
:
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 @
@
Run Code Online (Sandbox Code Playgroud)
从精细手册:
只要服务器返回模型的数据,在获取和保存时,就会调用parse.该函数传递给原始
response
对象,并应返回要在模型上设置的属性hash .
因此parse
,应该将服务器的响应按摩到可以set
在模型上的东西.您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()
Run Code Online (Sandbox Code Playgroud)
这在你看来:
initialize: (options) ->
console.log 'App.ItemViews.Thing init'
# Bind
@options.model.view = @
Run Code Online (Sandbox Code Playgroud)
您应该在创建模型时将模型传递给视图(您可以这样做):
App.Rendered.thingView = new App.ItemViews.Thing(model: App.Data.thing)
Run Code Online (Sandbox Code Playgroud)
然后视图应该绑定到模型:
initialize: (options) ->
@model.on('change', @render)
Run Code Online (Sandbox Code Playgroud)
您可以删除initialize
模型中的实现.
此外,您可以(并且应该)直接在命名空间中声明类,不要这样做:
class Thing extends Backbone.Marionette.ItemView
#...
App.ItemViews.Thing = Thing
Run Code Online (Sandbox Code Playgroud)
做这个:
class App.ItemViews.Thing extends Backbone.Marionette.ItemView
#...
Run Code Online (Sandbox Code Playgroud)
此外,setTimeout
几乎永远不会使用字符串/评估形式的邪恶.不要这样做:
setTimeout 'App.updateModel()', 2000
Run Code Online (Sandbox Code Playgroud)
做这个:
setTimeout (-> App.updateModel()), 2000
Run Code Online (Sandbox Code Playgroud)
可能会有更多,但希望这将使您开始并解决您的直接问题.
归档时间: |
|
查看次数: |
1286 次 |
最近记录: |