ChatGPT解决这个技术问题 Extra ChatGPT

主干.js 构建嵌套视图和模型

使用主干.js:

我有一个包含 2 个属性和 2 个嵌套模型 ModelB 和 ModelC 的顶级 ModelA。 ModelB 和 ModelC 各有 2 个属性,如下:

ModelA
    attributeA1
    attributeA2
    ModelB
        attributeB1
        attributeB2
    ModelC
        attributeC1
        attributeC2

ModelA 有一个 ViewA,ModelB 有一个 ViewB。 ViewA 的渲染函数将一个新的 div 放置到 body 上,而 ViewB 的渲染创建一个 h1。 ViewA 的初始化调用 ViewB 的渲染将 h1 插入到新的 div 中。这种分离背后的基本原理是 h1 可能会发生变化并需要独立于 ViewA 重新渲染。

ViewA
    initialise: 
        //call ViewA's own render function
        this.render() 

        //call ViewB's render function that further modifies the $("#new") div created earlier.
        $("#new").append(ViewB.render().el)

    //ViewA's own render function
    render: //place <div id="new"></div> onto 'body'

ViewB
    render: //create a <h1></h1>
    funcB1: //can this access it's parent ModelA's attributes and other objects?

Q1:ViewB 有一个函数 funcB1。这个函数可以访问它的父模型的属性吗?诸如attributeA1 之类的属性,甚至是attributeC1(这将是兄弟/表亲)?

Q2:作为 Q1 的进一步扩展,funcB1 可以访问与 ViewA 关联的 DOM 元素吗? (在这个例子中,#new div?)

Q3:一般来说,我如何定义上述视图和模型之间的关联,以便一切都正确地联系在一起?

我意识到这个问题有点抽象,但任何人都感谢任何帮助或指导。

您是否尝试过编写测试以查看这些测试是否能回答您的问题?
我尝试使用 Q1 和 Q2 的一些代码,但无法让它们工作。我认为提出这个问题的最好方法就是使用伪代码,并让更多精通 js 的人为我指明正确的方向。
我建议您用失败的代码编写单独的问题,以便 js 程序员可以指出问题所在。
当然,这很公平,我会尝试写一些。无论如何,如果有人仍然想提供任何意见,仍然欢迎!
这是一个相关(虽然更通用)的问题 &长答案以进一步了解这一点:stackoverflow.com/questions/10077185/…

U
UpCat

为了能够获得相关模型的属性,模型必须对它所关联的模型有某种了解。 Backbone.js 不会隐式处理关系或嵌套,这意味着您必须自己确保模型彼此了解。要回答您的问题,一种方法是确保每个子模型都有一个“父”属性。这样,您可以首先遍历嵌套到父级,然后再向下遍历到您知道的任何兄弟级。

更具体地回答您的问题。初始化modelA时,您可能正在创建modelB和modelC,我建议在执行此操作时设置到父模型的链接,如下所示:

ModelA = Backbone.Model.extend({

    initialize: function(){
        this.modelB = new modelB();
        this.modelB.parent = this;
        this.modelC = new modelC();
        this.modelC.parent = this;
    }
}

这样,您可以通过调用 this.parent 在任何子模型函数中访问父模型。

关于您的视图,在执行嵌套主干视图时,我发现使用视图的 tagName 选项让每个视图代表一个 HTML 标记更容易。我会把你的观点写成这样:

ViewA = Backbone.View.extend({

    tagName: "div",
    id: "new",

    initialize: function(){
       this.viewB = new ViewB();
       this.viewB.parentView = this;
       $(this.el).append(this.viewB.el);
    }
});

ViewB = Backbone.View.extend({

    tagName: "h1",

    render: function(){
        $(this.el).html("Header text"); // or use this.options.headerText or equivalent
    },

    funcB1: function(){
        this.model.parent.doSomethingOnParent();
        this.model.parent.modelC.doSomethingOnSibling();
        $(this.parentView.el).shakeViolently();
    }

});

然后在您的应用程序初始化代码中(例如在您的控制器中),我将启动 ViewA 并将其元素放置在 body 元素中。


如果可以,我有一个问题。在答案开始时在 ModelA 的 initialize 方法中创建 modelB 时,应该由 this.set('modelB') = new ModelB(); 设置还是在这种情况下不使用 setter 方法可以?
如果您希望关系位于模型的属性中(例如,能够绑定到更改事件),您可以使用 setter 方法。其语法是 this.set({modelB: new ModelB()})。但是,如果你想做更复杂的关系映射,我强烈推荐 Paul Uhitol 的主干关系或其他一些用于主干.js 的关系映射插件。
由于这会创建循环引用,是否存在任何内存泄漏?
请注意,如果 ViewA 有渲染方法,那么在初始化方法中将 B.el 附加到 A.el 将被破坏;您的示例仅有效,因为父级是无渲染视图。
诚然,这是一个警告。我仅将其用于类似控制器的视图
E
Elf Sternberg

“我可以”这个问题的一般答案总是“可以,只要你愿意编写代码”。 Backbone 背后的要点是提供模型和视图的强大分离。如果 B1 引用了 A1,而 A1 引用了 C1,那么您完全有能力创建方法并设置 B1 可以修改 A1 和 C1 的规则等等。

视图应设置为接收来自其各自模型的 CRUD 事件。如果用户对 B1view 进行了修改 B1model 的操作,而 B1model 又修改了 A1model,则 A1model 应该生成一个事件,A1view 接收并导致 A1view 重新渲染,依此类推。它应该像魔术一样发生。 (在实践中,需要一些时间才能获得正确的魔法,但我发现 Backbone 非常强大。BackboneRelational 有助于解决您在此处描述的问题。)


谢谢。我认为更准确的答案应该是“是的,只要你愿意并且能够编写代码”!
N
Nathan

上述解决方案在正确的轨道上,但存在一些问题。

initialize: function(){
  this.viewB = new ViewB();
  this.viewB.parentView = this;
  $(this.el).append(this.viewB.el);    
}

主要是,模型的 toJSON() 现在返回过时的数据。我在 backbone.js plugin 中发布了解决此问题的解决方案。欢迎您使用它。


A
Artem Oboturov

您可以使用一些扩展,例如 Backbone-Forms https://github.com/powmedia/backbone-forms。要遵循您的用例,请定义如下架构:

var ModelB = Backbone.Model.extend({
    schema: {
        attributeB1: 'Text',
        attributeB2: 'Text'
    }
});

var ModelC = Backbone.Model.extend({
    schema: {
        attributeC: 'Text',
    }
});

var ModelA = Backbone.Model.extend({
    schema: {
        attributeA1: 'Text',
        attributeA2: 'Text',
        refToModelB: { type: 'NestedModel', model: ModelB, template: 'templateB' },
        refToModelC: { type: 'NestedModel', model: ModelC, template: 'templateC' }
    }
});

查看 https://github.com/powmedia/backbone-forms#customising-templates 以获取部分模板。

这里的重要部分是 type: 'NestedModel'template: 'templateXXX'

此插件有一些限制,但您可以在 https://github.com/documentcloud/backbone/wiki/Extensions%2C-Plugins%2C-Resources 中查看其他插件。


G
Gagan

有骨干插件 Backbone-relational.js,它为 Backbone 的模型之间提供了一对一、一对多和多对一的关系。

我认为这个js会满足你的需求。访问 BackboneRelational 以获取更多文档。