Backbone.js보기에서 동적으로 id 및 className 설정


85

저는 Backbone.js를 배우고 사용하고 있습니다.

항목 모델과 해당 항목보기가 있습니다. 각 모델 인스턴스에는 해당 뷰의 'id'및 'class'속성으로 반영하고자하는 item_class 및 item_id 속성이 있습니다. 이것을 달성하는 올바른 방법은 무엇입니까?

예:

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'이 다음과 같이 변환되도록보기를 구현하는 방법은 무엇입니까?

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

내가 본 대부분의 예제에서 뷰의 el 은 '의미 론적'코드를 수동으로 작성 해야하는 의미없는 래퍼 요소 역할을합니다.

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로 직접 번역 되기를 원합니다 !

답변:


133

요약 : 모델 데이터로 뷰 속성을 동적으로 설정

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:)를 className설정하는 경우 DOM 속성 이름을 사용해야 하지만 attributes해시 / 메서드 를 통해 설정하는 경우 (이 예에서와 같이) 속성 이름을 사용해야합니다 class.

  • 백본 0.9.9 기준 :

    뷰를 선언 할 때 ... el, tagName, id그리고 className당신이 그 값은 런타임에 결정하려는 경우 이제 함수로 정의 할 수있다.

    attributes그림과 같은 방법 을 사용하는 대신 유용 할 수있는 상황이있는 경우이를 언급합니다 .

기존 요소 사용

기존 요소를 사용하는 경우 (예 : el뷰 생성자에 전달 ) ...

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

... 그러면 attributes요소에 적용되지 않습니다. 원하는 속성이 이미 요소에 설정되지 않은, 또는 당신이 당신의 뷰 클래스와 다른 위치에 데이터를 복제 할 수없는 경우에, 당신은 추가 할 수 있습니다 initialize적용보기 생성자에 방법 attributesel. 다음과 같은 것 (사용 jQuery.attr) :

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

el, 렌더링, 래퍼 방지 사용

내가 본 대부분의 예에서 뷰의 el은 '의미 론적'코드를 수동으로 작성해야하는 의미없는 래퍼 요소 역할을합니다.

아무 이유도 없다 view.el요구는 "요소 래퍼 의미없는"로. 사실, 그것은 종종 DOM 구조를 깨뜨릴 것입니다. <li>예를 들어 뷰 클래스가 요소를 나타내는 경우, <li>이를로 렌더링해야합니다. <div>또는 다른 요소 로 렌더링 하면 콘텐츠 모델이 손상됩니다. 당신은 가능성이 올바르게 뷰의 요소를 설정 (같은 속성을 사용하여 초점을 맞출 것이다 tagName, className하고 id) 다음의 렌더링 내용을 이후.

Backbone 뷰 객체가 DOM과 상호 작용하도록하는 방법에 대한 옵션이 넓게 열려 있습니다. 두 가지 기본 초기 시나리오가 있습니다.

  • 백본보기에 기존 DOM 요소를 첨부 할 수 있습니다.

  • 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 -->

템플릿은 전체보기를 나타냅니다. 즉, 템플릿 주위에는 래퍼가 없습니다 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() );
  }      
} );

속성 속성을 함수로 덮어 쓰고 객체를 다시 반환하는 멋진 방법입니다!
Kel

2
@Kel 예, 뷰가 인스턴스화되는 반복적 인 코드를 사용하지 않고 모델 데이터로 속성을 채우는 질문이 요구하는 것과 같은 동적 작업을 수행하는 좋은 방법입니다. 당신은 아마도 이것을 알고있을 것입니다. 그러나 그것이 분명하지 않은 경우를 대비하여 attributes, 함수 또는 다른 것으로 제공 될 수있는 많은 다른 Backbone 속성들처럼 해시를 값으로 반환하는 함수를 사용할 수있는 Backbone의 기능입니다. 가치 유형. 이 경우 Backbone은 값이 함수인지 확인하고이를 호출하고 반환 값을 사용합니다.
JMM

95

당신의 관점에서 다음과 같이하십시오.

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

이것은이 질문에 대한 정답이며 받아 들여 져야합니다
reach4thelasers

13
이 답변은 모델 데이터를 기반으로 뷰 속성을 동적으로 설정하는 것을 보여주지 않고 속성 값을 하드 코딩하는 대체 방법을 보여줍니다.
JMM 2012

3
@JMM-그의 샘플 코드도 모델 데이터를 사용하지 않습니다. 이 답변은 그의 샘플 코드를 기반으로 작동합니다. 분명히 모델 데이터가 값으로 대체 될 수 있습니다.
Clint

5
@ Clint, 나는 그것이 OP에 명백하다는 것을 믿지 않을 것입니다. "그의 샘플 코드도 모델 데이터를 사용하지 않습니다." -그것은 그가 방법을 모르기 때문에 그가 도움을 요청한 이유입니다. 그가 모델 데이터를 사용하여 view.el의 속성을 설정하는 방법을 묻는 것이 분명해 보이며 어떻게해야할지 모르겠습니다 . 대답은 그렇게하는 방법도 보여주지 않습니다. 왜 렌더링을 할 때까지 기다리거나 렌더링 할 때마다 다시 수행합니까? "이 답변은 작동합니다 ..."-작동 원리는 무엇입니까? 이렇게 생성 된 모든 뷰는 동일한 속성 값을 갖습니다. 그것이 보여주는 유일한 것은 래퍼를 피하는 방법입니다.
JMM

OP는 '12 년 2 월부터 사라졌습니다. :(이 답변에 대한 또 다른 +1이 있습니다.
Almo

27

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

편집 생성자 매개 변수를 기반으로 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;
}
// ...

3
그때마다 때문에 대답은 올바른 생각하지 않는 ItemView것입니다 id: 'id1'. 이 계산되어야하는 실행 시간 에 기초 model.id.
fguillen 2010 년

물론 원하는 방식으로 ID를 설정할 수 있습니다. 함수, 변수 또는 무엇이든 사용하십시오. 내 코드에는 루트 요소에 값을 설정하는 방법을 가리키는 예제가 포함되어 있습니다.
Jørgen 2012 년

생성자 매개 변수를 기반으로 동적으로 값을 설정하는 방법을 설명하는 예제를 추가했습니다.
Jørgen

이것이 정답입니다. Backbone 기능을 올바르게 사용하여 문제를 해결합니다.
Marc-Antoine Lemieux 2014

6

나는 그것이 오래된 질문이라는 것을 알고 있지만 참조를 위해 추가되었습니다. 이것은 새로운 백본 버전에서 더 쉬운 것 같습니다. 백본 1.1 ID와 클래스 이름 특성 함수에서 평가된다 ensureElement(참조 소스에서 밑줄 사용) _.result경우를 의미 className하거나 id, 그렇지 않으면 그 값이 사용되며,이 호출 될 함수이다.

따라서 생성자에서 직접 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'); }
});

귀하의 예를 들어 당신이 원하는 것, 유효하지 않습니다id: function() { return this.model.get('item_id'); })
코비 (cobby) 타입

4

다른 예는 모델에서 실제로 데이터를 가져 오는 방법을 보여주지 않습니다. 모델 데이터에서 ID 및 클래스를 동적으로 추가하려면 다음을 수행하십시오.

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

'this.className'또는 'this.class'입니까?
Gabe Rainbow

2

tagName을 제거하고 el을 선언해야합니다.

'tagName'은 백본이 요소를 생성하기를 원함을 나타냅니다. 요소가 이미 DOM에있는 경우 다음과 같은 el을 지정할 수 있습니다.

el: $('#emotions'),

이후 :

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

2

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

@Michel Pleasae는이 문서, backbonejs.org/#View-constructor
Hemanth

0

다음은 모델을 통해 뷰 요소의 클래스를 동적으로 변경하고 모델 변경시 업데이트하는 최소한의 방법입니다.

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 });
        }
    }
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.