javascript - 主干 View 继承

标签 javascript backbone.js

我知道有人会将其标记为重复,但我浏览了几乎所有与该主题相关的帖子,但这不是我要寻找的内容。这就是自上周以来困扰我的事情。

我的任务是创建 View 的原子设计。将有一个核心基础 View ,然后另一个 View 将扩展它,依此类推。 element->panel->window、element->panel->popup 等。使用 Backbone.View.extend 我可以简单地这样做

var BaseView = Backbone.View.extend({
  initialize : function(options) {
      this.$el.attr('cid', this.cid);
      this.base = options.base || arguments[0]['base'];
      this.parent = options.parent || arguments[0]['parent'];

      this.children = [];

      if(typeof this.template !== 'undefined') {
          if (typeof this.template=='function') {
              // do nothing. template is already a underscore template and will be parsed when first call;
          }
          else if (typeof this.template=='string' && this.template.substr(0,1)=='#') {
              if ($(this.template).length >0  ) {
                  this.template = _.template($(this.template).html());
              }
              else {
                  console.warn('Template element ' + this.template + 'could not be located in DOM.');
              }
          }
          else {
              this.template = _.template(this.template);
          }
      }
      else {
          this.template = _.template('<span></span>');
      }
      if (typeof this.parent!=='undefined' && this.parent ) {
          this.parent.add.apply(this.parent, [this]);
      }
  },
  add: function(child){
    this.children.push(child);
  },
  getChildren : function(){
    return this.children;
  },
  clean: function(){
    this.$el.empty();
  },

  close: function () {
      BaseView.prototype.clear.apply(this, [true]);
      this.undelegateEvents();
      this.unbind();
      this.stopListening();
      this.remove();
  },
  clear: function(){    
      if (this.children.length > 0) {
          empty = empty || false;
          _.each(this.getChildren(), function (child, index) {
              Baseview.prototype.close.apply(child);
          });
          this.children = [];
          if (empty) {
              this.$el.empty();
          }
      }
      return this;
  }
})

然后如果我尝试将其用作

var Layout = new BaseView.extend({
    el: '#someElement',
    template : '#sometemplate',
    initialize : function(){
      this.childView = new ChildView({parent: this, base: this, collection: someCollection});
      return this;
    },
    render: function(){
        this.clean().$el.append(this.template({}));
        this.$('.content').append(this.childView.render().$el);
        return this;
    },
});

var ChildView = BaseView.extend({
  tagName : 'div',
  template : '#childTemplate',
  initialize : function(){
    return this;
  },
  render: function(){
    var self = this;
    this.clean().$el.append(this.template({}));
    this.$list = this.$('ul');
    _.each( this.collection.models, function(model){     
        var grandChildView = new GrandChildView({parent: self, base: self.base, model: model});
        self.$list.append(grandChildView.render().$el);
    })
    return this;
  }
});


var GrandChildView = BaseView.extend({
  tagName : 'li',
  template : '#grandChildTemplate',
  initialize : function(){
    return this;
  },
  render: function(){
     this.clean().$el(this.template(this.model.toJSON()));
     return this;
  }
});
$(function(){
  new Layout();
})

不起作用,因为 Backbone 不是在 BaseView 上运行初始化,而是首先调用初始化,并且 this.template 和所有其他都未定义。

然后我尝试将其替换为构造函数,而不是在 BaseView 上初始化。但后来我最终出现了 this.$el 未定义错误,因为 Backbone.View.constructor 尚未被调用,所以还没有 this.$el 正在由 创建>_ensureElement

所以经过一些研究,我发现唯一的就是使用

Backbone.View.prototype.constructor.apply(this,[options]);

但这也会导致类似的问题,在 Backbone.View 的末尾,调用 this.initialize.apply(this, [options]),然后转到子对象初始化。所以我被困住了,无法理解这个问题。

我也知道我可以从 subview 调用父 View 的初始化函数,但这并不可取,因为有很多 subview 相互扩展。这就是我传递父对象以将以后的对象附加到其子对象的原因。

我想要完成的是创建一个包装器扩展对象,我可以稍后为另一个对象扩展它,但同时它应该在原始基本 View 上运行一些常见任务,附加额外的原型(prototype)方法,然后调用调用者初始化。

如此伪

var BaseView {
   extend Backbone view with the passed arguments, 
   check for base, parent arguments and set them
   check for template option, if exists then get the element, create template function and replace with the string one,
   if there is parent view passed, then attach yourself to children of parent
   call your own initialize method,
   return 
}

最佳答案

如果我理解正确的话,您想在实例化 subview 时运行“父 View ”的初始化方法吗?如果这是正确的,请参阅这篇文章:https://stackoverflow.com/a/8596882/1819684

您缺少的是主干文档中有关该帖子中引用的“ super ”的注释。

根据您的评论,我认为这就是您正在寻找的。您必须在主干中显式调用“ super ”方法(父类的方法),如我引用的帖子所示。您可以在调用父方法之前和之后在“初始化”中执行您想要/需要执行的任何操作。我还发现了这个:Defining child views without an initialize method这可能会有所帮助。

var BaseView = Backbone.View.extend({
  el: '#container1',
  initialize: function(){
    console.log('base view init');
    this.render();
  },
  render: function(){
    this.$el.html("Hello World 1");
  }
});

var ChildView = BaseView.extend({
  el: '#container2',
  initialize: function() {
    console.log('before call to parent (BaseView) init');
    BaseView.prototype.initialize.apply(this, arguments);
    console.log('ChildView init');
  },
  render: function(){
    this.$el.html("Hello World 2");
  }
});

var GrandChildView = ChildView.extend({
  el: '#container3',
  initialize: function() {
    console.log('before call to parent (ChildView) init');
    ChildView.prototype.initialize.apply(this, arguments);
    console.log('GrandChildView init');
  },
  render: function(){
    this.$el.html("Hello World 3");
  }
});


var appView = new BaseView();
var appView = new ChildView();
var appView = new GrandChildView();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone.js"></script>

<div id="container1">Loading...</div>
<div id="container2">Loading...</div>
<div id="container3">Loading...</div>

关于javascript - 主干 View 继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43813498/

相关文章:

javascript - 解析一个 JSON 字符串并显示它

javascript - 添加 .animation 更改链接标记内跨度的背景颜色不起作用

JavaScript 代码没问题,但网页预览只显示我的 html 工作

javascript - felixge/node-mysql 无法连接到数据库

javascript - 如何在 backbone.js 中动态定义事件

javascript - 浏览器使用错误路径加载 Typescript js.map 文件

javascript - Backbone.js - 防止 PUT/POST on model.validate 失败

backbone.js - 监听器绑定(bind)到模型属性未触发

javascript - 与 Rest 一起使用的主干集合不起作用

javascript - Backbone js - 更改模型属性