使用 Backbone-relational 在 Backbone 中创建嵌套模型 [英] Creating nested models in Backbone with Backbone-relational

查看:18
本文介绍了使用 Backbone-relational 在 Backbone 中创建嵌套模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 backbone-relational 在我的 backbone.js 应用程序.

I would like to use backbone-relational to have nested models in my backbone.js application.

我已经能够按照文档中的示例创建嵌套对象(例如一对多关系).但是我不明白如何以更新上层对象的方式绑定下层元素.我认为一个有效的应用程序将是一个非常有用的教程.

I have been able to follow the examples in the documentation to create nested objects (e.g. one-to-many relations). However I don't understand how to bind the lower level elements in a way that will update the upper level objects. I think a working application would be a very helpful tutorial.

所以我的问题是:如何扩展 Todos 教程使用 backbone-relational 以便:

So my question is: How do I extend the Todos tutorial using backbone-relational so that:

  • 可以为每个项目添加/删除子项目
  • 双击任何子项对其进行编辑(就像原始 Todo 示例一样)
  • 点击一个项目会隐藏/显示它的子项目
  • 子项目不是单独获取的,而是简单的 Todo 项目的数组属性

更新:我已经为此问题创建了一个 jsfiddle.到目前为止,我有:

Update: I have created a jsfiddle for this question. So far I have:

  • 导入上面提到的 Todo 示例
  • 创建了一个 TodoSubitem 模型和一个 TodoSubitemList 集合
  • 改变了 Todo 模型以扩展 RelationalModel 而不是 Model,与 具有 HasMany 关系TodoSubitem
  • 在html代码中添加了subitem-template
  • Imported the Todo example mentioned above
  • Created a TodoSubitem model and a TodoSubitemList collection
  • Altered the Todo model to extend RelationalModel instead of Model, with a HasMany relation to TodoSubitem
  • Added a subitem-template in the html code

但我仍然不确定如何:

  • subitems 添加一个输入字段,该字段仅在您单击 Todo div 时出现
  • 将子项目数据作为Todo 对象的一个​​属性,但仍然有TodoSubitemView 将DOM 元素绑定到它们(例如
  • 标签).
  • add an input field for subitems that appears only when you click a Todo div
  • have subitem data as an attribute of Todo objects, but still have TodoSubitemView bind DOM elements to them (e.g. <li> tags).

推荐答案

我不认为在这种情况下我会创建一个单独的TodoSubItem" - 为什么不从 Todo 创建一个 HasMany 关系->Todo,所以一个 Todo 可以有 0..* children 和 0..1 parent?

I don't think I'd create a separate 'TodoSubItem' in this case - why not create a HasMany relation from Todo->Todo, so a Todo can have 0..* children, and 0..1 parent?

通过这种方式,您可以重新使用顺序逻辑(如果您将其更改为应用到每个集合),可以根据需要创建更深的嵌套级别(或将其限制为特定深度,如果您愿意)等.尽管如此,许多事情需要更新,以适应这一点 - 例如,保留一个子视图列表,以便您可以遍历它们以将每个视图标记为已完成,并维护(和更新)每个 TodoList 的排序.

This way, you can re-use the order logic (if you change it to apply per collection), can create deeper nesting levels as desired (or limit that to a certain depth, if you want as well), etc. A number of things will need to be updated though, to accomodate this - for example, keep a list of child views so you can loop over them to mark each as done, and maintaining (and updating from) an ordering per TodoList.

无论如何,粗略概述一个可能的解决方案来帮助您入门,作为与您当前版本的一种差异(抱歉,它完全未经测试,因此可能包含可怕的错误):

Anyway, a rough outline of a possible solution to get you started, as a sort of diff with your current version (sorry, it's completely untested and could thus contain horrible mistakes):

//Our basic **Todo** model has `text`, `order`, and `done` attributes.
window.Todo = Backbone.RelationalModel.extend({

    relations: [{
        type: Backbone.HasMany,
        key: 'children',
        relatedModel: 'Todo',
        collectionType: 'TodoList',
        reverseRelation: {
            key: 'parent',
            includeInJSON: 'id'
        }
    }],

    initialize: function() {
        if ( !this.get('order') && this.get( 'parent' ) ) {
            this.set( { order: this.get( 'parent' ).nextChildIndex() } );
        }
    },

    // Default attributes for a todo item.
    defaults: function() {
        return { done: false };
    },

    // Toggle the `done` state of this todo item.
    toggle: function() {
        this.save({done: !this.get("done")});
    }

    nextChildIndex: function() {
        var children = this.get( 'children' );
        return children && children.length || 0;
    }
});


// The DOM element for a todo item...
window.TodoView = Backbone.View.extend({

    //... is a list tag.
    tagName:  "li",

    // Cache the template function for a single item.
    template: _.template($('#item-template').html()),

    // The DOM events specific to an item.
    events: {
        'click': 'toggleChildren',
        'keypress input.add-child': 'addChild',
        "click .check"              : "toggleDone",
        "dblclick div.todo-text"    : "edit",
        "click span.todo-destroy"   : "clear",
        "keypress .todo-input"      : "updateOnEnter"
    },

    // The TodoView listens for changes to its model, re-rendering.
    initialize: function() {
        this.model.bind('change', this.render, this);
        this.model.bind('destroy', this.remove, this);

        this.model.bind( 'update:children', this.renderChild );
        this.model.bind( 'add:children', this.renderChild );

        this.el = $( this.el );

        this.childViews = {};
    },

    // Re-render the contents of the todo item.
    render: function() {
        this.el.html(this.template(this.model.toJSON()));
        this.setText();

        // Might want to add this to the template of course
        this.el.append( '<ul>', { 'class': 'children' } ).append( '<input>', { type: 'text', 'class': 'add-child' } );

        _.each( this.get( 'children' ), function( child ) {
            this.renderChild( child );
        }, this );

        return this;
    },

    addChild: function( text) {
        if ( e.keyCode == 13 ) {
            var text = this.el.find( 'input.add-child' ).text();
            var child = new Todo( { parent: this.model, text: text } );
        }
    },

    renderChild: function( model ) {
        var childView = new TodoView( { model: model } );
        this.childViews[ model.cid ] = childView;
        this.el.find( 'ul.children' ).append( childView.render() );
    },

    toggleChildren: function() {
        $(this.el).find( 'ul.children' ).toggle();
    },

    // Toggle the `"done"` state of the model.
    toggleDone: function() {
        this.model.toggle();
        _.each( this.childViews, function( child ) {
            child.model.toggle();
        });
    },

    clear: function() {
        this.model.set( { parent: null } );
        this.model.destroy();
    }

    // And so on...
});

这篇关于使用 Backbone-relational 在 Backbone 中创建嵌套模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆