Javascript 如何将视图/模型的引用传递到backbone.js中的其他视图/模型/路由

Javascript 如何将视图/模型的引用传递到backbone.js中的其他视图/模型/路由,javascript,backbone.js,Javascript,Backbone.js,因此,我对backbone.js非常陌生,我正在尝试理解让部件(视图/模型/路线)与其他部件交互的基本概念 这里有一个例子。我有一个“屏幕”模型对象被“单屏幕”视图呈现到页面上。我还有一个“侧边栏”模型和正在渲染的视图。当我点击侧边栏中的链接时,我希望它呈现一个不同的屏幕模型对象,并根据我给屏幕模型的“name”属性在一个单独的HTML div(标题)中修改一些HTML 那么第一个问题,所有用于重新呈现不同视图和更改标题html的代码都应该在routes.js文件中完成吗?看起来那个文件会很快变

因此,我对backbone.js非常陌生,我正在尝试理解让部件(视图/模型/路线)与其他部件交互的基本概念

这里有一个例子。我有一个“屏幕”模型对象被“单屏幕”视图呈现到页面上。我还有一个“侧边栏”模型和正在渲染的视图。当我点击侧边栏中的链接时,我希望它呈现一个不同的屏幕模型对象,并根据我给屏幕模型的“name”属性在一个单独的HTML div(标题)中修改一些HTML

那么第一个问题,所有用于重新呈现不同视图和更改标题html的代码都应该在routes.js文件中完成吗?看起来那个文件会很快变大。如果是这样的话,我如何获得对我想在routes.js文件中呈现的模型对象的引用,以便访问myModel.name(在app.js文件中实例化)之类的内容

我是否将浏览器历史记录和视图呈现作为单独的内容处理,并在我的app.js文件(我实例化所有对象的文件)中添加“单击链接,呈现此”功能的代码?如果是这样的话,如果用户试图通过键入URL而不是单击直接进入视图,我的应用程序如何知道要呈现什么

或者,据我所知,这是最可能的情况

我是否使用模型/视图的初始化函数在单击链接(或更改主干.history())并调用render时触发/侦听事件

我把这三种方法都弄糟了,但我不明白如何将对象引用传递到应用程序的其他部分,而不只是将这些对象设置为全局变量(这感觉非常错误)

在最后一个场景中,我把事件弄得一团糟,但我所读到的每一处都说必须包含对它正在侦听的对象的引用,这似乎违背了设置事件对象并侦听事件的全部目的,而不仅仅是查询该对象变量的状态

例如

如何将对sidebarModel对象的引用传递给singleScreen视图,以使其了解要侦听的内容


我并不是真的在寻找一个编码的答案,更重要的是,我只是了解最佳实践和事情应该如何去做。我感觉我很接近,但我知道我遗漏了/不理解一些东西,这就是为什么我自己不能弄明白这一点,所以对整个主题有点启发将不胜感激。谢谢

首先,您需要了解每个主干类的作用。先读一读可能会有所帮助

模型 渲染视图时不需要模型。它的作用是处理数据,数据可以是本地的,也可以来自API。所有影响数据的函数都应该在模型中,并且模型不应该有任何与渲染相关的内容

总会有例外,您可以使用模型来处理仅与渲染相关的数据,但当您发现这种情况时就会知道

一本书就是一个简单的例子:

// The Book model class
var Book = Backbone.Model.extend({ 
    idAttribute: 'code',
    urlRoot: '/api/book'
});

// a Book instance
var solaris = new Book({ code: "1083-lem-solaris" });
从API获取将调用:

// GET http://example.com/api/book/1083-lem-solaris
solaris.fetch(); // this is async
获取时,API返回JSON编码的数据

{
    "code": "1083-lem-solaris",
    "title": "Test title",
}
属性将与现有属性合并,添加尚未存在的属性,并覆盖已存在属性的值

收集 集合的作用是管理模型数组,这些模型可以是本地的,也可以从API获取。它应该只包含与管理集合相关的功能

var Library = Backbone.Collection.extend({
  model: Book,
  url: '/api/book'
});

var myLibrary = new Library();

// just adds an existing book to our array
myLibrary.add(solaris);
您可以从API获取集合以获取现有书籍的数组:

myLibrary.fetch();
API应返回:

[
    { "code": "blah-code-123", "title": "Test title" }, 
    { "code": "other-code-321", "title": "Other book title" } 
]
{ "code": "new-code-123", "title": "my new book" }, 
使用集合创建新书并与API同步:

var myNewBook = myLibrary.create({ title: "my new book" });
这将发送带有属性的POST请求,API应返回:

[
    { "code": "blah-code-123", "title": "Test title" }, 
    { "code": "other-code-321", "title": "Other book title" } 
]
{ "code": "new-code-123", "title": "my new book" }, 
看法 视图处理其根DOM元素。它应该处理来自其DOM的事件。它最好用于包装小组件,并从较小的组件中构建较大的组件

将链接直接放在锚定标记的
href
模板中。没有必要为此使用事件

<a href="#my-route">link</a>`
事件 主干中的所有内容都有mixin,甚至还有全局主干对象。因此,每个类都可以使用
listenTo
将回调绑定到事件



要深入了解主干网中的所有内容还需要很长时间,所以提出问题,我将尝试扩展我的答案

太棒了,谢谢你的解释。好的,我想我遇到的问题是,我试图创建一个对象的实例并将其传递给其他人,而看起来您的任务是创建一个新实例并将所需的值作为参数传递。(我假设如果不再需要它,就清理旧实例。)示例,其中创建
var model=newbook({code:code})
为了进一步解释我为什么要挂断它,我决定尝试创建一个应用程序,你可以想象它知道你的图书馆将只有4本书,并且你已经知道它们的所有属性值。所以我一开始就试图在app.js中创建这4本书,然后传递引用。但我开始理解实际处理它的最好方法是用相关数据创建一个新的图书模型实例。这意味着基于我的书本模型中的数据在routes.js之类的东西中操作DOM是不可能的;在您的路线中,您有权访问该信息吗?因为在创建要渲染的book的新实例时,您只传入了
code
。@MattyB在我的示例中,我假设在
url:'/books'
上有一个假的API,我使用
fetch
从服务器检索看起来像
{code:'123',title:'my title',等等}
的数据。谢谢!
var LibraryRouter = Backbone.Router.extend({
    routes: {
        '*index': 'index',
        'book/:code': 'bookRoute',
    },

    index: function() {
        var library = new LibraryView({
            el: 'body',
            // hard-coded collection as a simple example
            collection: new Library([
                { "code": "blah-code-123", "title": "Test title" }, 
                { "code": "other-code-321", "title": "Other book title" } 
            ])
        });
        library.render();
    },
    bookRoute: function(code) {
        var model = new Book({ code: code });
        // here, I assume an API is available and I fetch the data
        model.fetch({
            success: function() {
                var view = new BookPageView({
                    el: 'body',
                    model: model
                });
                view.render();
            }
        });
    }
});