3

バックボーンJSビューは、構成可能なタグ、ID、およびクラスを使用して、常にDOMノードを作成するという点で非常に「便利」です。これは非常に素晴らしく、順応性がありますが、残念な状況が発生することがわかりました。ビューによって作成されたDOMノードは非表示のテンプレートです。

これは、フロントエンドとバックエンドの間でMustacheテンプレートを共有している現在のプロジェクトで明らかになりました。バックボーンを使用して、次のようなDOMが必要な場合:

<section class="note">
  <textarea>
  ...
  </textarea>

  <input type="button" class="save-button" value="Save">
  <input type="button" class="cancel-button" value="Cancel">
</section>

最終的に次のようなテンプレートを作成します。

<textarea>
{{& content}}
</textarea>

<input type="button" class="save-button" value="Save">
<input type="button" class="cancel-button" value="Cancel">

ただし、これで、テンプレートはバックボーンビューのシークレットルートノードテンプレートに関連付けられます。これは、サーバー側で複製する必要があります。DRYカプセル化についてはこれだけです!

setElement()レンダリング時にレンダリングされたテンプレートを使用する場合を除いて、これに対処するためのすぐに明白な方法はわかりませんが、これにより、DOMで新しくレンダリングされたサブツリーを毎回置き換える必要があるなど、他の問題が発生しrender()ます。

この問題にどのように対処しましたか?

4

2 に答える 2

3

興味深い質問です。これまでこの特定の問題を解決する必要はありませんでしたが、いくつかのオプションを試してみて、気に入ったオプションを見つけたと思います。

まず、コードは次のとおりです。

//A base view which assumes the root element of its
//template (string, DOM node or $) as its el.
var RootlessView = Backbone.View.extend({

    //override the view constructor
    constructor: function(options) {

        //template can be provided by constructor argument or
        //as a subclass prototype property
        var template = options.template || this.template;

        //create a detached DOM node out of the template HTML
        var $el = Backbone.$(template).clone()

        //set the view's template to the inner html of the element
        this.template = $el.html(); 

        //set the element to the template root node and empty it
        this.el = $el.empty()[0];

        //call the superclass constructor
        Backbone.View.prototype.constructor.apply(this, arguments);
    }
});

基本的に、すべての派生ビューがtemplateプロパティを持つかtemplate、オプション ハッシュの引数として を受け取ることを期待するベース ビューを定義します。テンプレートは、文字列、DOM ノード、または jQuery/Zepto でラップされた DOM ノードにすることができます。ビューは、テンプレートのルート ノードをその として想定し、プロパティをルート ノードのコンテンツelとして再定義します。template

通常のビューとして使用します。

var View = RootlessView.extend({
    template: templateHtml,
    render: function() {
        this.$el.html(Mustache.render(this.template, this.model));
        return this;
    }
}); 

このelプロパティは最初から利用可能であり、再レンダリング時にデタッチおよび再アタッチされることはありません。通常の動作の唯一の例外は、、またはプロパティまたは引数Backbone.Viewを定義した場合、テンプレートがルート要素を提供するため、それらは無視されることです。idcssClasstagName

これは広範囲にテストされていませんが、ほとんどの単純なテスト ケースに合格しているようです。私が考えることができる唯一の欠点は、templateHTML 文字列が (プロトタイプではなく) すべてのビュー インスタンスに格納され、貴重なメモリ バイトを浪費することですが、それも解決するのは難しいことではありません。

これはJSFiddle で動作するデモです

于 2013-01-23T01:09:21.963 に答える
2

解決策は、共有ベース テンプレート (子なし) にルート ノード自体 (この場合はセクション タグ) を含め、インスタンス化時にビューの「el」プロパティを初期化することです。

var existingElement = $('section.note')[0];
new View({el: existingElement}) 

その後、フォーム テンプレートを通常どおり el プロパティに添付できます。

于 2013-01-23T00:10:22.147 に答える