program tip

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

radiobox 2020. 9. 15. 07:44
반응형

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


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


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

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/

생성 된 요소

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

In your view just do something like this

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

You can set the properties className and id on the root element: 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 Included example of setting id based on constructor parameters

If the views are constructed as mentioned:

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

Then the values could be set this way:

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

I know it's an old question, but added for reference. This seems to be easier in new backbone versions. In Backbone 1.1 the id and className properties are evaluated in the function ensureElement (see from source) using underscore _.result meaning if className or id is a function, it will be called, otherwise its value will be used.

So you could give className directly in the constructor, give another parameter that would be used in the className, etc... Plenty of options

so this should work

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

The other examples are not showing how to actually grab the data from the model. To dynamically add id and class from the model's data:

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

You need to remove tagName and declare an el.

'tagName' signifies that you want backbone to create an element. If the element already exists in the DOM, you can specify an el like:

el: $('#emotions'),

and later:

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

Try to assign the values in initialize method this will directly assign id and class to the div attribute dynamically.

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

Here's a minimal way to change the class of the view's element dynamically via a model and update it on model changes.

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

참고URL : https://stackoverflow.com/questions/7033134/setting-id-and-classname-dynamically-in-backbone-js-views

반응형