2

I am trying to use templating to render a view initially, but to update the view on subsequent calls when it is part of the document.

My app's page looks a little something like

<body>
  <!-- ... -->
  <div id="view_placeholder"/>
  <!-- ... -->
</body>

And in pseudo-code I want to do something like so

Backbone.View.extend({
  // ...
  render: function() {
    if (this.el *IS NOT A CHILD OF document*) {
      // render the contents from the template
    } else {
      // update the content visibility based on the model
    }
  },
  // ...
});

The reason for this is that the template contains quite a lot of nodes and regenerating it for every change is not practicable.

I have explored some of the data-binding libraries, e.g. rivets.js but they are a poor fit to the template:model relation.

One thing I noticed is that this.el.parentNode==null before I add it to the document, but I am not sure that this is a definitive test, and in any case if I wrap this view within another, then that test becomes less useful (or maybe I am being overly cautious as once within another view's el I have rendered my sub-template anyway.

Another option I can see is to use a field to track the rendered status, e.g.

Backbone.View.extend({
  //
  templateRendered:false,
  // ...
  render: function() {
    if (!this.templateRendered) {
      // render the contents from the template
      this.templateRendered = true;
    } else {
      // update the content visibility based on the model
    }
  },
  // ...
});

but that feels hacky to me.

So my question is:

What is the best way to track the fact that I have rendered the template fully and therefore only need to tweak the rendered template rather than re-render it (and re-insert all the sub-views)?

4

2 回答 2

1

我认为惯用的主干方法是仅在需要完整渲染时才在视图上调用完整render()视图,并使用模型更改事件绑定来调用渲染较小部分视图的子渲染函数。

var AddressView = Backbone.View.extend({
    initialize: function (options) {
        Backbone.view.prototype.initialize.call(this, options);
        _.bindAll(this)
        options.model.on('change:name', this.renderName);
        options.model.on('change:street', this.renderStreet);
        options.model.on('change:zipCode', this.renderZipCode);
    },
    renderName: function (model) {
        this.$el.find("#name").text(model.get("name"));
    },
    renderZipCode: function (model) {
        this.$el.find("#zipcode").text(model.get("zipCode"));
    },
    renderStreet: function (model) {
        this.$el.find("#stree").text(model.get("street"));
    },
    render: function () {
        //Populate this.el with initial template, subviews, etc
        //assume this.template is a template function that can render the main HTML
        this.$el.html(this.template(model));
        this.renderName(this.model);
        this.renderZipCode(this.model);
        this.renderStreet(this.model);
        return this;
    }
});

上面的代码无疑是乏味的。我个人会重新考虑knockback.jsrivets.js,但我相信上面的模式是典型的 vanillabone.js 方法。

于 2012-10-31T14:08:42.537 回答
0

在即将插入其元素之前,我会避免渲染视图。在任何情况下,您都可以通过检查视图元素的父级来找到,即

 this.$el.parent()

this.$el如果不是您的文档的一部分,则应为空。

于 2012-10-31T18:59:49.240 回答