在Backbone.js视图中动态设置id和className

uz75evzq  于 2022-11-10  发布在  其他
关注(0)|答案(8)|浏览(161)

我正在学习和使用Backbone.js的过程中。
我有一个项目模型和一个相应的项目视图。每个模型例程都有item_class和item_id属性,我希望将这些属性反映为相应视图的'id'和'class'属性。实现此目的的正确方法是什么?
示例:

var ItemModel = Backbone.Model.extend({      
});

var item1 = new ItemModel({item_class: "nice", item_id: "id1"});
var item2 = new ItemModel({item_class: "sad", item_id: "id2"});

var ItemView = Backbone.View.extend({       
});

我应该如何实现视图,以便视图的el 's将转换为:

<div id="id1" class="nice"></div>
<div id="id2" class="sad"> </div>

在我看到的大多数例子中,视图的el充当了一个无意义的 Package 器元素,在其中必须手动编写“语义”代码。

var ItemView = Backbone.View.extend({
   tagName:  "div",   // I know it's the default...

   render: function() {
     $(this.el).html("<div id="id1" class="nice"> Some stuff </div>");
   }       
});

所以当渲染的时候

<div> <!-- el wrapper -->
    <div id="id1" class="nice"> Some stuff </div>
</div>

但这似乎是一种浪费-为什么要有外部div?我想让el直接翻译成内部div!

5rgfhyps

5rgfhyps1#

摘要:使用模型数据动态设置视图属性

http://jsfiddle.net/5wd0ma8b/

// View class with `attributes` method
var View = Backbone.View.extend( {
  attributes : function () {
    // Return model data
    return {
      class : this.model.get( 'item_class' ),
      id : this.model.get( 'item_id' )
    };
  }
  // attributes
} );

// Pass model to view constructor
var item = new View( {
  model : new Backbone.Model( {
    item_class : "nice",
    item_id : "id1"
  } )
} );
  • 这个例子假设您允许Backbone为您生成一个DOM元素。
  • attributes方法是在设置传递给视图构造函数的属性之后调用的(在本例中为model),允许您在Backbone创建el之前使用模型数据动态设置属性。
  • 与其他一些答案相反:不硬编码视图类中的属性值,而是从模型数据中动态设置它们;不会等到render()才设置属性值;不会在每次调用render()时重复设置属性值;无需手动设置DOM元素的属性值。
  • 请注意,如果在调用Backbone.View.extend或视图构造函数(例如new Backbone.View)时设置类,则必须使用DOM属性名称className,但如果通过attributes hash /方法(如本例中所示)设置类,则必须使用属性名称class
  • 自 Backbone.js 0.9.9起:

声明视图时... eltagNameidclassName现在可以定义为函数(如果您希望在运行时确定它们的值)。
我之所以提到这一点,是因为在某些情况下,它可以作为使用attributes方法的替代方法,如图所示。

使用现有元素

如果您使用的是现有元素(例如,将el传递给视图构造函数)...

var item = new View( { el : some_el } );

...那么attributes将不会应用于该元素。如果所需的属性尚未在元素上设置,或者您不想在视图类和其他位置复制该数据,那么您可能需要在视图构造函数中添加一个initialize方法,该方法将attributes应用于el。如下所示(使用jQuery.attr):

View.prototype.initialize = function ( options ) {
  this.$el.attr( _.result( this, 'attributes' ) );
};

使用el,呈现,避免 Package

在我看到的大多数例子中,视图的el充当了一个无意义的 Package 器元素,在其中必须手动编写“语义”代码。
没有理由view.el必须是“一个无意义的 Package 器元素”。事实上,这经常会破坏DOM结构。例如,如果一个视图类表示一个<li>元素,需要将其呈现为<li>--将其呈现为<div>或任何其他元素将破坏内容模型。您'我很可能希望重点关注正确设置视图的元素(使用tagNameclassNameid等属性),然后呈现其 * 内容 *。
如何让你的 Backbone.js 视图对象与DOM交互的选项是完全开放的。有两个基本的初始场景:

  • 您可以将现有的DOM元素附加到 Backbone.js 视图。
  • 您可以允许Backbone创建一个与文档断开连接的新元素,然后以某种方式将其插入文档。

有多种方法可以生成元素的内容(设置一个文字字符串,如示例中所示;使用模板库,如Mustache、Handlebars等)。如何使用视图的el属性取决于您正在执行的操作。

现有元素

您的渲染示例表明您已经有一个元素要分配给视图,尽管您没有显示视图的示例化。如果是这种情况,并且该元素已经在文档中,那么您可能需要执行类似这样的操作(更新el的内容,但不要更改el本身):

render : function () {
  this.$el.html( "Some stuff" );
}

http://jsfiddle.net/vQMa2/1/

生成的元素

假设你没有一个现有的元素,你让Backbone为你生成一个,你 * 可能 * 想做这样的事情(但是最好是架构一些东西,这样你的视图就不会知道它本身之外的任何东西):

render : function () {
  this.$el.html( "Some stuff" );
  $( "#some-container" ).append( this.el );
}

http://jsfiddle.net/vQMa2/

模板

在我的例子中,我使用的是模板,例如:

<div class="player" id="{{id}}">
<input name="name" value="{{name}}" />
<input name="score" value="{{score}}" />
</div>
<!-- .player -->

模板表示完整的视图,换句话说,模板周围没有 Package 器--div.player将是我的视图的根元素或最外层元素。
我的播放器类看起来像这样(非常简化的render()示例):

Backbone.View.extend( {
  tagName : 'div',
  className : 'player',

  attributes : function () {
    return {
      id : "player-" + this.model.cid
    };
  },
  // attributes

  render : function {
    var rendered_template = $( ... );

    // Note that since the top level element in my template (and therefore
    // in `rendered_template`) represents the same element as `this.el`, I'm
    // extracting the content of `rendered_template`'s top level element and
    // replacing the content of `this.el` with that.
    this.$el.empty().append( rendered_template.children() );
  }      
} );
zpgglvta

zpgglvta2#

在你看来就做这样的事

var ItemView = Backbone.View.extend({
   tagName:  "div",   // I know it's the default...

   render: function() {
     $(this.el).attr('id', 'id1').addClass('nice').html('Some Stuff'); 
   }       
});
ovfsdjhp

ovfsdjhp3#

您可以在根元素上设置属性classNameid:http://documentcloud.github.com/backbone/#View-extend

var ItemView = Backbone.View.extend({
   tagName:  "div",   // I know it's the default...
   className : 'nice',
   id : 'id1',
   render: function() {
     $(this.el).html("Some stuff");
   }       
});

EDIT包含基于构造函数参数设置id的示例

如果视图按上述方式构建:

var item1 = new ItemModel({item_class: "nice", item_id: "id1"});
var item2 = new ItemModel({item_class: "sad", item_id: "id2"});

然后,可以按以下方式设置这些值:

// ...
className: function(){
    return this.options.item_class;
},
id: function(){
    return this.options.item_id;
}
// ...
jw5wzhpr

jw5wzhpr4#

我知道这是一个老问题,但添加它是为了参考。在新的 Backbone.js 版本中,这似乎更容易。在Backbone 1.1中,id和className属性在函数ensureElement(见源代码)中使用下划线_.result进行计算,这意味着如果classNameid是一个函数,则将调用它,否则将使用它的值。
因此,您可以直接在构造函数中给予className,提供将在className中使用的另一个参数,等等...有很多选项
所以这个应该能用

var item1 = new ItemModel({item_class: "nice", item_id: "id1"});
var item2 = new ItemModel({item_class: "sad", item_id: "id2"});

var ItemView = Backbone.View.extend({       
  id: function() { return this.model.get('item_id'); },
  className: function() { return this.model.get('item_class'); }
});
fumotvh3

fumotvh35#

其他示例并没有展示如何从模型中获取数据。要从模型的数据中动态添加id和class:

var ItemView = Backbone.View.extend({
   tagName:  "div",

   render: function() {
     this.id = this.model.get('item_id');
     this.class = this.model.get('item_class');
     $(this.el).attr('id',this.id).addClass(this.class).html('Some Stuff'); 
   }       
});
nkcskrwz

nkcskrwz6#

您需要删除tagName并声明一个el。
'tagName'表示您希望 Backbone.js 创建一个元素。如果该元素已经存在于DOM中,您可以指定如下的el:

el: $('#emotions'),

和更新版本:

render: function() { 
     $(this.el).append(this.model.toJSON());
}
atmip9wb

atmip9wb7#

尝试在initialize方法中分配值,这将直接动态地将id和class分配给div属性。

var ItemView = Backbone.View.extend( {
    tagName : "div",   
    id      : '',
    class   : '',

    initialize : function( options ) {
        if ( ! _.isUndefined( options ) ) {
            this.id = options.item_id;
            this.class= options.item_class;
        }
    },

    render : function() {
        $( this.el ).html( this.template( "stuff goes here" ) ); 
    }
} );
qjp7pelc

qjp7pelc8#

下面是一个通过模型动态更改视图元素的类并在模型更改时更新它的最小方法。

var VMenuTabItem = Backbone.View.extend({
    tagName: 'li',
    events: {
        'click': 'onClick'
    },
    initialize: function(options) {

        // auto render on change of the class. 
        // Useful if parent view changes this model (e.g. via a collection)
        this.listenTo(this.model, 'change:active', this.render);

    },
    render: function() {

        // toggle a class only if the attribute is set.
        this.$el.toggleClass('active', Boolean(this.model.get('active')));
        this.$el.toggleClass('empty', Boolean(this.model.get('empty')));

        return this;
    },
    onClicked: function(e) {
        if (!this.model.get('empty')) {

            // optional: notify our parents of the click
            this.model.trigger('tab:click', this.model);

            // then update the model, which triggers a render.
            this.model.set({ active: true });
        }
    }
});

相关问题