javascript - 如何在 Backbone.js 中呈现和附加 subview

标签 javascript model-view-controller backbone.js

我有一个嵌套 View 设置,它可以深入我的应用程序。我可以想到多种方法来初始化、渲染和附加 subview ,但我想知道常见的做法是什么。

这是我想到的几个:

initialize : function () {

    this.subView1 = new Subview({options});
    this.subView2 = new Subview({options});
},

render : function () {

    this.$el.html(this.template());

    this.subView1.setElement('.some-el').render();
    this.subView2.setElement('.some-el').render();
}

优点:您不必担心通过追加来维护正确的 DOM 顺序。 View 在早期就已初始化,因此在渲染函数中没有那么多事情要同时完成。

缺点:您被迫重新委托(delegate)事件(),这可能代价高昂?父 View 的渲染函数被所有需要发生的 subview 渲染弄得一团糟?您无法设置元素的 tagName,因此模板需要维护正确的 tagName。

另一种方式:

initialize : function () {

},

render : function () {

    this.$el.empty();

    this.subView1 = new Subview({options});
    this.subView2 = new Subview({options});

    this.$el.append(this.subView1.render().el, this.subView2.render().el);
}

优点:您不必重新委派事件。您不需要仅包含空占位符的模板,并且您的标签名称将返回由 View 定义。

缺点:您现在必须确保以正确的顺序附加内容。父 View 的渲染仍然被 subview 渲染弄得一团糟。

使用 onRender 事件:

initialize : function () {
    this.on('render', this.onRender);
    this.subView1 = new Subview({options});
    this.subView2 = new Subview({options});
},

render : function () {

    this.$el.html(this.template);

    //other stuff

    return this.trigger('render');
},

onRender : function () {

    this.subView1.setElement('.some-el').render();
    this.subView2.setElement('.some-el').render();
}

优点: subview 逻辑现在与 View 的 render() 方法分离。

使用 onRender 事件:

initialize : function () {
    this.on('render', this.onRender);
},

render : function () {

    this.$el.html(this.template);

    //other stuff

    return this.trigger('render');
},

onRender : function () {
    this.subView1 = new Subview();
    this.subView2 = new Subview();
    this.subView1.setElement('.some-el').render();
    this.subView2.setElement('.some-el').render();
}

我在所有这些示例中混合并匹配了一系列不同的做法(很抱歉),但是您会保留或添加哪些做法?你不会做什么?

实践总结:

  • initializerender 中实例化 subview ?
  • renderonRender 中执行所有 subview 渲染逻辑?
  • 使用 setElement 还是 append/appendTo

最佳答案

我通常看到/使用过几种不同的解决方案:

解决方案一

var OuterView = Backbone.View.extend({
    initialize: function() {
        this.inner = new InnerView();
    },

    render: function() {
        this.$el.html(template); // or this.$el.empty() if you have no template
        this.$el.append(this.inner.$el);
        this.inner.render();
    }
});

var InnerView = Backbone.View.extend({
    render: function() {
        this.$el.html(template);
        this.delegateEvents();
    }
});

这与您的第一个示例类似,但有一些变化:

  1. 附加子元素的顺序很重要
  2. 外部 View 不包含要在内部 View 上设置的 html 元素(意味着您仍然可以在内部 View 中指定 tagName)
  3. render() 在内部 View 的元素被放入 DOM 之后调用,如果您的内部 View 的 render() 方法正在放置/调整自身大小,这将很有帮助基于其他元素的位置/大小在页面上(根据我的经验,这是一个常见的用例)

方案二

var OuterView = Backbone.View.extend({
    initialize: function() {
        this.render();
    },

    render: function() {
        this.$el.html(template); // or this.$el.empty() if you have no template
        this.inner = new InnerView();
        this.$el.append(this.inner.$el);
    }
});

var InnerView = Backbone.View.extend({
    initialize: function() {
        this.render();
    },

    render: function() {
        this.$el.html(template);
    }
});

解决方案 2 可能看起来更简洁,但根据我的经验,它导致了一些奇怪的事情,并对性能产生了负面影响。

出于以下几个原因,我通常使用解决方案 1:

  1. 我的很多观点都依赖于已经在 DOM 中的 render() 方法
  2. 当重新渲染外部 View 时,不必重新初始化 View ,重新初始化可能会导致内存泄漏,还会导致现有绑定(bind)出现异常问题

请记住,如果每次调用 render() 时都初始化一个 new View(),则该初始化将调用 delegateEvents() 无论如何。因此,正如您所表达的那样,这不一定是“骗局”。

关于javascript - 如何在 Backbone.js 中呈现和附加 subview ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9271507/

相关文章:

php - JQuery 数组和输入复选框+隐藏

c# - 在登录中验证 EMAIL-MVC

用于非常简单的单页原型(prototype)的 Javascript 框架

javascript - 主干集合获取选项不影响 GET 请求

javascript - backbone 路由,backbone.history 启动后的多个路由器

javascript - 如何将委托(delegate)事件分配给特定的 Dom 元素

javascript - 将自定义类名添加到 jquery 日历单元格

javascript - 使用括号表示法在对象内部调用函数

c# - ViewBag 不保存状态

javascript - 如何从 Backbone.listenTo 中查找触发事件?