在Backbone.js的意见设置的ID和动态的className [英] Setting id and className dynamically in Backbone.js views

查看:89
本文介绍了在Backbone.js的意见设置的ID和动态的className的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在学习过程和使用Backbone.js的。

我有一个项目模型和相应的项目视图。
每个模型实例都有item_class和ITEM_ID属性,我想反映在作为ID和类对应的视图属性。
什么是实现这一目标的正确方法?

例如:

VAR ItemModel = Backbone.Model.extend({
});VAR ITEM1 =新ItemModel({item_class:好,ITEM_ID:ID1});
VAR ITEM2 =新ItemModel({item_class:伤心,ITEM_ID:ID2});VAR ItemView控件= Backbone.View.extend({
});

我应该如何实现视图这样的意见厄尔尼诺的将转化为:

< D​​IV ID =ID1级=好好先生>< / DIV>
< D​​IV ID =ID2级=悲伤> < / DIV>

在我所见到的大多数例子中,视图的作为内哪一个具有手动编写了语义code无意义的包装元素。

VAR ItemView控件= Backbone.View.extend({
   标签名:格,//我知道这是默认......   渲染:功能(){
     $(this.el)的.html(< D​​IV ID =ID1级=好好先生>有些东西与LT; / DIV>中);
   }
});

所以渲染时,一个得到

< D​​IV> <! - 埃尔包装 - >
    < D​​IV ID =ID1级=好好先生>有些东西< / DIV>
< / DIV>

不过,这似乎是一种浪费 - 为什么有外部的div?我想在将直接转化为内部的div!


解决方案

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

http://jsfiddle.net/5wd0ma8b/

  //查看类`attributes`方法
VAR查看= Backbone.View.extend({
  属性:功能(){
    //返回模型数据
    返回{
      等级:this.model.get('item_class'),
      ID:this.model.get('ITEM_ID')
    };
  }
  //属性
});//传递模型查看构造
VAR项目=新的View({
  型号:新Backbone.Model({
    item_class:好,
    ITEM_ID:ID1
  })
});


  • 本示例假设你允许骨干为您生成一个DOM元素。


  • 后传递给视图的构造属性设置(在这种情况下,属性方法被调用时,模式),使骨干创建之前,动态设置与模型数据的属性


  • 在与一些其他的答案:不硬code属性值在视图类,动态地设置他们的模型数据;没有等到渲染()设置ATTR丘壑;不重复设置在每次调用ATTR丘壑到渲染();没有不必要的手动设置DOM元素上ATTR丘壑。


  • 请注意,如果设置类调用时 Backbone.View.extend 或视图构造(如新Backbone.View ),您必须使用DOM属性名,的className ,但如果通过设置它的属性散/方法(如本例),你必须使用属性的名称,


  • 为骨干的0.9.9:


      

    在声明查看... 标签名 ID 的className 现在可以,如果你想在运行时确定其价值定义为功能。


    我提到这一点的情况下,还有一种情况,那将是有益的,以替代使用属性方法如图所示。


使用现有的元素

如果您使用的是现有元素(例如通过到视图构造函数)...

  VAR项目=新的View({EL:some_el});

...那么属性将不会被应用到元素。如果所需的属性尚未设置的元素上,或者你不希望复制在您的视图类和其他位置的数据,那么你可能要添加初始化方法到您的视图构造适用属性。像这样的事情(使用 jQuery.attr

  View.prototype.initialize =功能(选件){
  这$ el.attr(_.result(这一点,'属性'));
};

EL的用法,渲染,避免了包装


  

在我所见到的大多数例子中,视图的EL作为内哪一个具有手动编写了语义code无意义的包装元素。


有没有理由 view.el 需要一个毫无意义的包装元素。事实上,这将经常破坏DOM结构。如果一个视图类重presents一个<李>例如元素,它必须呈现为<李> - 渲染它作为一个< D​​IV> 或任何其他元素会打破内容模型。你可能会希望把重点放在如何正确设置视图的元素(使用类似标签名的className 属性和 ID ),然后渲染它的内容的之后。

有关如何让你的骨干视图对象与DOM交互的选项是敞开的。有2个基本初始情况:


  • 您可以将现有的DOM元素为骨干视图。


  • 您可以让骨干创建从文档中断开的新元素,然后以某种方式将其插入到文档中。


有多种方法可以生成元素含量(设置一个文本字符串,如您的示例;使用模板库像小胡子,把手等)。你应该如何使用视图的属性取决于你在做什么。

现有元素

您呈现例子表明,你有,你分配给该视图中存在的元素,虽然你不显示的看法实例。如果是这样的话,和元素已经在文档中,那么你可能需要做这样的事情(更新的内容,但不改变本身):

 渲染:功能(){
  这$ el.html(一些东西);
}

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

生成元素

让我们说你没有一个现有的元素,你让骨干生成一个给你。您的可能的想这样做(但很可能最好的建筑师的事情,所以,你的看法是不负责了解有关自身之外的任何东西):

 渲染:功能(){
  这$ el.html(一些东西);
  $(#一些容器).append(this.el);
}

http://jsfiddle.net/vQMa2/

模板

在我的情况下,我使用的模板,例如:

 < D​​IV CLASS =玩家ID ={{ID}}>
<输入名称=名字值={{名}}/>
<输入名称=得分值={{得分}}/>
< / DIV>
&所述;! - .player - >

模板重新presents的完整视图。换句话说,将有大约模板没有包装 - div.player 将根目录或我的观点的最外层元素

我的播放器类将是这个样子(与)的很简单的例子渲染():

  Backbone.View.extend({
  标签名:'格',
  产品类别:'球员',  属性:功能(){
    返回{
      ID:播放器 - + this.model.cid
    };
  },
  //属性  渲染:{功能
    VAR rendered_template = $(...);    //注意,由于在模板中的顶级元素(并且因此
    //在`rendered_template`)再presents同样的元素`this.el`,我
    //提取`rendered_template`的顶级元素的内容,
    //替换的`this.el`与该内容。
    。这$ el.empty()追加(rendered_template.children());
  }
});

I am in process of learning and using Backbone.js.

I have an Item model and a corresponding Item view. Each model instance has item_class and item_id attributes, that I want to be reflected in as the 'id' and 'class' attributes of the corresponding view. What's the correct way to achieve this ?

Example:

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({       
});

How should I implement the view so that the the views 'el's will translate to:

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

In most examples I have seen, the view's el serves as a meaningless wrapper element inside which one has to manually write the 'semantic' code.

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>");
   }       
});

So when rendered, one gets

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

But this seems like a waste - why have the external div ? I want the el to translate directly into the internal div!

解决方案

Summary: dynamically set view attributes with model data

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"
  } )
} );

  • This example assumes that you're allowing Backbone to generate a DOM element for you.

  • The attributes method is called after the properties passed to the view constructor are set (in this case, model), allowing you to dynamically set the attributes with the model data before Backbone creates el.

  • In contrast to some of the other answers: doesn't hard-code attribute values in the view class, dynamically sets them from model data; doesn't wait until render() to set attr vals; doesn't repeatedly set attr vals in every call to render(); doesn't unnecessarily manually set attr vals on DOM element.

  • Note that if setting the class when calling Backbone.View.extend or a view constructor (e.g. new Backbone.View), you have to use the DOM property name, className, but if setting it via the attributes hash / method (as in this example) you have to use the attribute name, class.

  • As of Backbone 0.9.9:

    When declaring a View...el, tagName, id and className may now be defined as functions, if you want their values to be determined at runtime.

    I mention this in case there's a situation where that would be useful as an alternative to using an attributes method as illustrated.

Using an existing element

If you're using an existing element (e.g. passing el to the view constructor)...

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

...then attributes won't be applied to the element. If the desired attributes aren't already set on the element, or you don't want to duplicate that data in your view class and another location, then you may want to add an initialize method to your view constructor that applies attributes to el. Something like this (using jQuery.attr):

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

Usage of el, rendering, avoiding the wrapper

In most examples I have seen, the view's el serves as a meaningless wrapper element inside which one has to manually write the 'semantic' code.

There's no reason view.el needs to be "a meaningless wrapper element". In fact, that would often break the DOM structure. If a view class represents a <li> element for example, it needs to be rendered as an <li> -- rendering it as a <div> or any other element would break the content model. You'll likely want to focus on correctly setting up your view's element (using properties like tagName, className, and id) and then rendering its content thereafter.

The options for how to have your Backbone view objects interact with the DOM are wide open. There are 2 basic initial scenarios:

  • You can attach an existing DOM element to a Backbone view.

  • You can allow Backbone to create a new element that is disconnected from the document, then somehow insert it into the document.

There are various ways you can generate the content for the element (set a literal string, as in your example; use a templating library like Mustache, Handlebars, etc.). How you should use the el property of the view depends what you're doing.

Existing element

Your rendering example suggests that you have an existing element that you're assigning to the view, although you don't show instantiation of the views. If that's the case, and the element is already in the document, then you may want to do something like this (update the content of el, but don't alter el itself):

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

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

Generated element

Let's say you don't have an existing element and you allow Backbone to generate one for you. You may want to do something like this (but it's likely better to architect things so that your view isn't responsible for knowing about anything outside itself):

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

http://jsfiddle.net/vQMa2/

Templates

In my case, I'm using templates, e.g.:

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

The template represents the complete view. In other words, there will be no wrapper around the template -- div.player will be the root or outermost element of my view.

My player class will look something like this (with very simplified example of 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() );
  }      
} );

这篇关于在Backbone.js的意见设置的ID和动态的className的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆