Javascript 主干JS将扩展模型添加到其继承模型类型的集合中

Javascript 主干JS将扩展模型添加到其继承模型类型的集合中,javascript,backbone.js,backbone.js-collections,class-extensions,Javascript,Backbone.js,Backbone.js Collections,Class Extensions,我刚刚开始深入研究backboneJS,并在codepen()中构建了一个小型文本应用程序。一切进展顺利,但我有一个问题:一旦用户点击提交按钮,我希望表单容器视图: 解析所有表单字段。这些是多种模型类型(标题字段、所见即所得文本编辑器等),以及一个集合(tagInput.collection-用户放入的所有标记) 创建一个标准化的JSON对象,该对象包含用户提供给应用程序的所有数据,并将其传递给服务器 目前,我正在尝试将Backbone.Model扩展到一个新的类“FormModel”,它只包含

我刚刚开始深入研究backboneJS,并在codepen()中构建了一个小型文本应用程序。一切进展顺利,但我有一个问题:一旦用户点击提交按钮,我希望表单容器视图:

  • 解析所有表单字段。这些是多种模型类型(标题字段、所见即所得文本编辑器等),以及一个集合(tagInput.collection-用户放入的所有标记)
  • 创建一个标准化的JSON对象,该对象包含用户提供给应用程序的所有数据,并将其传递给服务器
  • 目前,我正在尝试将Backbone.Model扩展到一个新的类“FormModel”,它只包含默认属性“value”。然后,我在主容器上创建一个新集合,其中包含容器中的所有各种模型。因此,container.collection的模型是FormModel,但我尝试.add()的所有实际模型都是FormModel的扩展类。这可能吗?每当我尝试访问集合时,它总是空的!我觉得我缺少了理解底层逻辑指导主干的一些关键部分,但我不能确切地说是什么

    (我认为是)相关代码附在下面。我最新版本的“迷你应用程序”的完整代码也链接在上面:

    //LINE 9 in Full Code
    // Generic, very simply model type for any type of form entry that we can extend
      var FormModel = Backbone.Model.extend({
        defaults: {
          value: '',
        }
      });
    
      //Input class definition
      var input = {};
      input.model = FormModel.extend({
        defaults: {
          placeHolder: 'Enter Title Here...',
          class: '',
          warn: 'a title',
          size: '20px'
        }
      });
      input.view = Backbone.View.extend({
        events: {
          'keypress input': 'checkKey',
          'change input': 'updateValue'
        },
        initialize: function() {
          _.bindAll(this, 'render', 'checkKey', 'doSubmit','updateValue');
          this.render();
        },
        render: function() {
          if (this.model.get('class')) {
            $(this.el).addClass(this.model.get('class'));
          }
          $(this.el).append('<div class="clearButton inputClear"></div>');
          $(this.el).append('<input type="text" placeHolder="'+this.model.get('placeHolder')+'" style="font-size: '+this.model.get('size')+'">');
          this.clickable = true;
          return this;
        },
        checkKey: function(e) {
          if (e.keyCode === 13) {
            this.doSubmit();
          }
        },
        doSubmit: function() {
          var thisVal = this.updateValue();
          if (thisVal.length > 0) {
          } else {
            alert('Hey, you need to '+this.model.get('warn')+' before you can submit this post!');
          }
        },
        updateValue: function() {
          var thisVal  = $('input', this.el).val();
          this.model.set('value', thisVal);
          return thisVal;
        },
      });
    
    
    
    /*
     *[...]
     */
    
    
    
    //LINE 132 in Full Code
    //Tag class definition
      var tag = {};
      tag.model = FormModel.extend({
        defaults: {
          title: '',
          exists: false,
          parent: $('#container'),
        }
      });
      tag.view = Backbone.View.extend({
        events: {
          'click .clearButton': 'kill',
        },
        initialize: function() {
          _.bindAll(this, 'render', 'kill');
          this.render();
        },
        render: function() {
          $(this.el).addClass('tagRow');
          $(this.el).html(this.model.get('title'));
          $(this.el).append('<div class="clearButton tagClose"></div>');
          this.clickable = true;
          return this;
        },
        kill: function() {
          if (this.clickable) {
            this.clickable = false;
            var that = this;
            $(this.el).animate({opacity: 0}, 500, function(){
              $(that.el).remove();
              this.model.destroy();
            });
          }
        }
      });
      tag.collection = Backbone.Collection.extend({
        model: tag.model,
      });
    
    
    
    /*
     *[...]
     */
    
    
    
    //LINE 214 in Full Code
      //Container class definition
      var container = {};
      container.collection = Backbone.Collection.extend({
        model: FormModel
      });
      container.model = Backbone.Model.extend({
      });
      container.view = Backbone.View.extend({
        el: $('body'),
        initialize: function() {
          _.bindAll(this, 'render', 'appendItem', 'newTag', 'makeTagDialog', 'validate');
          this.collection = new container.collection();
          this.fields = [];
          this.render();
        },
        render: function() {
          $('body').append('<div id="container"></div>');
          this.container = $('body #container');
    
          var title = new input.model({
            placeHolder: 'Enter Title Here...',
            class: 'subArea titleArea',
            warn: 'a title',
          });
          this.appendItem(new input.view({model: title}).el);
    
          this.appendItem(new editor.view({model: new editor.model()}).el);
          this.makeTagDialog();
    
          var submitButton = new submit.view({model: new submit.model()});
          this.listenTo(submitButton.model, 'change:counter', this.validate);
          $(this.container).append(submitButton.el);
    
          return this;
        },
        appendItem: function(view) {
          this.collection.add(view.model);
          $(this.container).append(view);
        },
        makeTagDialog: function() {
          this.container.append('<div class="subArea tagDialog"></div>');
          var tags = $('.tagDialog', this.container);
          tags.append('<div class="tagArea"></div>');
          var tagInput = new input.view({
            model: new input.model({ 
              placeHolder: 'Tag Your Post...',
              class: 'tagInput',
              warn: 'at least one tag',
              size: '16px',
              value: ''
            })
          });
          tagInput.addTag = function() {
            if (this.model.get('value').length) {
              this.collection.add(new tag.model({
                title: this.model.get('value')
              }));
            }
            this.clearInput();
          };
          tagInput.model.on('change:value', tagInput.addTag, tagInput);
          this.appendItem(tagInput.el);
          $('.tagInput .clearButton').css('marginTop', '-2px');
    
          tagInput.collection = new tag.collection();
          tagInput.collection.on('add', this.newTag);
        },
        newTag: function(model) {
            thisView = new tag.view({model: model});
            thisView.parent = this;
            $('.tagArea', this.container).append(thisView.el);
        },
        validate: function(){
          alert('Form validation launched!');
          var form = [];
          this.collection.each(function(value) {
            form.push(value);
          });
        }
      });
    
    new container.view({model: container.model});
    })(jQuery);
    
    //完整代码中的第9行
    //通用的,非常简单的模型类型,用于我们可以扩展的任何类型的表单条目
    var FormModel=Backbone.Model.extend({
    默认值:{
    值:“”,
    }
    });
    //输入类定义
    var输入={};
    input.model=FormModel.extend({
    默认值:{
    占位符:“在此处输入标题…”,
    类别:“”,
    警告:“标题”,
    尺寸:'20px'
    }
    });
    input.view=Backbone.view.extend({
    活动:{
    “按键输入”:“检查键”,
    “更改输入”:“更新值”
    },
    初始化:函数(){
    _.bindAll(这是'render','checkKey','doSubmit','updateValue');
    这个。render();
    },
    render:function(){
    if(this.model.get('class')){
    $(this.el).addClass(this.model.get('class');
    }
    $(this.el)。追加(“”);
    $(this.el)。追加(“”);
    this.clickable=true;
    归还这个;
    },
    检查键:功能(e){
    如果(如keyCode===13){
    这是doSubmit();
    }
    },
    doSubmit:function(){
    var thisVal=this.updateValue();
    如果(thisVal.length>0){
    }否则{
    警告('嘿,你需要'+this.model.get('warn')+'才能提交此帖子!');
    }
    },
    updateValue:function(){
    var thisVal=$('input',this.el).val();
    this.model.set('value',thisVal);
    返回此值;
    },
    });
    /*
    *[...]
    */
    //第132行完整代码
    //标记类定义
    var tag={};
    tag.model=FormModel.extend({
    默认值:{
    标题:“”,
    存在:错误,
    父项:$(“#容器”),
    }
    });
    tag.view=Backbone.view.extend({
    活动:{
    'click.clearButton':'kill',
    },
    初始化:函数(){
    _.bindAll(这是“呈现”、“杀死”);
    这个。render();
    },
    render:function(){
    $(this.el).addClass('tagRow');
    $(this.el).html(this.model.get('title');
    $(this.el)。追加(“”);
    this.clickable=true;
    归还这个;
    },
    kill:function(){
    如果(此选项可单击){
    this.clickable=false;
    var=这个;
    $(this.el).animate({opacity:0},500,function(){
    $(that.el).remove();
    this.model.destroy();
    });
    }
    }
    });
    tag.collection=Backbone.collection.extend({
    型号:tag.model,
    });
    /*
    *[...]
    */
    //第214行完整代码
    //容器类定义
    var容器={};
    container.collection=Backbone.collection.extend({
    模型:FormModel
    });
    container.model=Backbone.model.extend({
    });
    container.view=Backbone.view.extend({
    el:$(“正文”),
    初始化:函数(){
    _.bindAll(这是'render','appendItem','newTag','makeTagDialog','validate');
    this.collection=新容器.collection();
    this.fields=[];
    这个。render();
    },
    render:function(){
    $('body')。追加('');
    this.container=$('body#container');
    var title=new input.model({
    占位符:“在此处输入标题…”,
    类别:“分区标题区”,
    警告:“标题”,
    });
    this.appendItem(新的input.view({model:title}).el);
    this.appendItem(new editor.view({model:new editor.model()}).el);
    这个.makeTagDialog();
    var submitButton=new submit.view({model:new submit.model()});
    this.listenTo(submitButton.model,'change:counter',this.validate);
    $(this.container).append(submitButton.el);
    归还这个;
    },
    附录项:函数(视图){
    this.collection.add(view.model);
    $(this.container).append(视图);
    },
    makeTagDialog:function(){
    this.container.append(“”);
    var tags=$('.tagDialog',this.container);
    标签。附加(“”);
    var tagInput=new input.view({
    模型:新输入。模型({
    占位符:“标记您的帖子…”,
    类:“tagInput”,
    警告:“至少有一个标记”,
    大小:“16px”,
    值:“”
    })
    });
    tagInput.addTag=函数(){
    if(this.model.get('value').length){
    this.collection.add(new tag.model({
    标题:this.model.get('value'))
    }));
    }
    这个.clearInput();
    };
    tagInput.model.on('change:value',tagInput.addTag,tagInput);
    此.appendItem(tagInput.el);
    $('.tagInput.clearButton').css('marginTop','-2px');
    tagInput.collection=新的tag.collection();
    tagInput.collection.on('add',this.newTag);
    },
    新标签:功能(模型){
    thisView=new tag.view({model:model});
    thisView.parent=this;
    $('.tagArea',this.cont
    
    this.appendItem(new input.view({model: title}).el);
    
    appendItem: function(view) {
        this.collection.add(view.model);
        $(this.container).append(view.el);
    },
    
    this.appendItem(new editor.view({model: new editor.model()}));