bestsource

Backbone.js에서 하위 뷰를 초기화하고 렌더링하는 방법은 무엇입니까?

bestsource 2023. 7. 23. 14:33
반응형

Backbone.js에서 하위 뷰를 초기화하고 렌더링하는 방법은 무엇입니까?

뷰와 뷰의 하위 뷰를 초기화하고 렌더링하는 방법은 세 가지가 있는데 각각 다른 문제가 있습니다.이 모든 문제를 해결할 수 있는 더 나은 방법이 있는지 궁금합니다.


시나리오 1:

부모의 초기화 기능에서 자식을 초기화합니다.이렇게 하면 모든 항목이 렌더링에 고정되지 않으므로 렌더링 시 차단이 줄어듭니다.

initialize : function () {

    //parent init stuff

    this.child = new Child();
},

render : function () {

    this.$el.html(this.template());

    this.child.render().appendTo(this.$('.container-placeholder');
}

문제:

  • 가장 큰 문제는 부모에서 렌더를 두 번째 호출하면 모든 자식 이벤트 바인딩이 제거된다는 것입니다.(이것은 jQuery의 방식 때문입니다.$.html()작동합니다.)이 문제는 전화로 해결할 수 있습니다.this.child.delegateEvents().render().appendTo(this.$el);대신, 하지만 첫 번째, 그리고 가장 빈번한 경우, 당신은 불필요하게 더 많은 일을 하고 있습니다.

  • 자식을 추가하면 렌더 함수가 부모 DOM 구조에 대한 지식을 갖게 되어 원하는 순서를 얻을 수 있습니다.즉, 템플릿을 변경하려면 뷰의 렌더 기능을 업데이트해야 합니다.


시나리오 2:

초상기위항화에 있는 합니다.initialize()여전히, 하지만 추가하는 대신 사용합니다.setElement().delegateEvents()부모 템플릿의 요소로 자식을 설정합니다.

initialize : function () {

    //parent init stuff

    this.child = new Child();
},

render : function () {

    this.$el.html(this.template());

    this.child.setElement(this.$('.placeholder-element')).delegateEvents().render();
}

문제:

  • 이것은 다음을 만듭니다.delegateEvents()지금 필요합니다. 첫 번째 시나리오에서 후속 통화에만 필요하다는 점에서 약간 부정적입니다.

시나리오 3:

초상기위항화에 있는 합니다.render()대신 방법.

initialize : function () {

    //parent init stuff
},

render : function () {

    this.$el.html(this.template());

    this.child = new Child();

    this.child.appendTo($.('.container-placeholder').render();
}

문제:

  • 이는 이제 렌더 기능이 모든 초기화 로직과 연결되어야 함을 의미합니다.

  • 자식 보기 중 하나의 상태를 편집한 다음 부모에서 렌더를 호출하면 완전히 새로운 자식이 만들어지고 현재 상태가 모두 손실됩니다.이것은 또한 메모리 누수에 대한 위험을 초래할 수도 있는 것처럼 보입니다.


당신들의 부하들이 이것을 받아들일지 정말 궁금합니다.어떤 시나리오를 사용하시겠습니까?아니면 이 모든 문제를 해결하는 네 번째 마법이 있을까요?

보기에 대해 렌더링된 상태를 추적한 적이 있습니까?세이아renderedBefore깃발? 정말 장난치는 것 같아요.

이것은 훌륭한 질문입니다.백본은 가정이 부족하기 때문에 좋지만, 이와 같은 것을 구현하는 방법을 직접 결정해야 한다는 것을 의미합니다.제 물건을 살펴본 결과 시나리오 1과 시나리오 2를 혼합하여 사용하고 있습니다.저는 제 4의 마법 시나리오가 존재한다고 생각하지 않습니다. 왜냐하면 시나리오 1과 2에서 여러분이 하는 모든 것이 이루어져야 하기 때문입니다.

예를 들어 제가 어떻게 처리하고 싶은지 설명하는 것이 가장 쉬울 것 같습니다.지정된 보기로 분할된 간단한 페이지가 있다고 가정합니다.

Page Breakdown

HTML이 렌더링된 후 다음과 같은 것이라고 가정합니다.

<div id="parent">
    <div id="name">Person: Kevin Peel</div>
    <div id="info">
        First name: <span class="first_name">Kevin</span><br />
        Last name: <span class="last_name">Peel</span><br />
    </div>
    <div>Phone Numbers:</div>
    <div id="phone_numbers">
        <div>#1: 123-456-7890</div>
        <div>#2: 456-789-0123</div>
    </div>
</div>

HTML이 다이어그램과 어떻게 일치하는지가 꽤 분명하기를 바랍니다.

ParentView두 개의 하위 보기를 보유하고 있습니다.InfoView그리고.PhoneListView디브뿐만 , 그 중인, 몇개의여디뿐아만니라는, 그중하나의브분,는그중하s,#name어느 시점에서 설정해야 합니다.PhoneListView, 의 체하보위보, 의련일이 있습니다.PhoneViewentries

곧 실제 질문으로 넘어갑니다.보기 유형에 따라 초기화 및 렌더링을 다르게 처리합니다.저는 제 견해를 두 가지 유형으로 나눕니다.Parent 및 뷰및Child 뷰, 뷰

그들사차간단니다합은이점이의다.Parent하는 동안 하위 뷰를 유지합니다.Child보기는 그렇지 않습니다.그래서 제 예에서는,ParentView그리고.PhoneListViewParent에 기보, 안동InfoView 리고그고.PhoneView은 "품작은출"입니다.Child 뷰, 뷰

앞서 언급했듯이, 이 두 범주의 가장 큰 차이점은 렌더링이 허용될 때입니다.완벽한 세상에서, 나는 원합니다.Parent한 번만 렌더링할 수 있습니다.모델이 변경될 때 재렌더링을 처리하는 것은 하위 뷰에 달려 있습니다.Child반면에 뷰는 다른 뷰에 의존하지 않기 때문에 필요할 때마다 다시 렌더링할 수 있습니다.

조금 더 자세히 말하자면,Parent내가 좋아하는 견해들initialize과 같은합니다.

  1. 내 보기 초기화
  2. 내 보기 렌더링
  3. 하위 보기를 만들고 초기화합니다.
  4. 에서 각 " " " " " " " " " " " " " "InfoView할당될 것입니다.#info).

1단계는 상당히 자기 설명적입니다.

2단계인 렌더링은 하위 보기에 의존하는 요소가 이미 존재하도록 한 후 할당하려고 합니다.이렇게 함으로써, 나는 모든 아이를 압니다.events올바르게 설정될 것이고, 나는 아무것도 다시 위임할 필요 없이 원하는 만큼 그들의 블록을 다시 렌더링할 수 있습니다.사실은 그렇지 않습니다.render여기에 있는 모든 아이들의 견해, 나는 그들이 그들 자신의 안에서 그것을 하도록 허용합니다.initialization.

제가 3단계를 할 때 됩니다.el하위 보기를 만드는 동안.저는 부모가 아이가 자신의 관점에서 콘텐츠를 넣을 수 있는 위치를 결정해야 한다고 생각하기 때문에 여기에 요소를 전달하고 싶습니다.

렌더링을 위해, 저는 그것을 매우 단순하게 하려고 노력합니다.Parent뷰. 나는 그것을 원합니다.render부모 보기를 렌더링하는 것 이상의 작업을 수행하지 않습니다.이벤트 위임도 없고 하위 보기 렌더링도 없고 아무것도 없습니다.단순한 렌더링입니다.

가끔 이것이 항상 효과가 있는 것은 아닙니다.를 들어, 를들어제, 예에서위의예위예,,#name모델 내의 이름이 변경될 때마다 요소를 업데이트해야 합니다. 이 은▁of의 입니다.ParentView 및 으로 처리되지 않는 템플릿Child합니다. 그, 래서저그해결합니다을것는뷰다▁view니.제가 어떤 것을 만들 것입니다.subRender의 내용만 대체하는 기능#name가 없습니다.#parentㅠㅠㅠㅠ , 는 전체 하고 요소를 다시 하는 것등에 하는 것보다 것을 알게 .이것은 해킹처럼 보일 수도 있지만, 저는 전체 DOM을 다시 렌더링하고 요소를 다시 부착하는 것 등에 대해 걱정하는 것보다 더 잘 작동한다는 것을 알게 되었습니다.만약 내가 정말로 깨끗하게 만들고 싶다면, 나는 새로운 것을 만들 것입니다.Child)InfoView) 를할 수 #name블록으로 막다

, 이제 은음다입니다.Child 뷰,initialization와 상당히 유사합니다.Parent조회할 수 .Child 기보. 그래서:

  1. 내 보기 초기화
  2. 원하는 모델의 변경 내용을 수신하는 중인 설정
  3. 내 보기 렌더링

Child간단하며, 내 뷰렌링간매다의 됩니다. 컨텐츠를 렌더링하고 설정하기만 하면 됩니다.el다시 말하지만, 대표단이나 그런 것들을 방해하지 마세요.

여기 내가 사용하는 것의 몇 가지 예제 코드가 있습니다.ParentView다음과 같이 보일 수 있습니다.

var ParentView = Backbone.View.extend({
    el: "#parent",
    initialize: function() {
        // Step 1, (init) I want to know anytime the name changes
        this.model.bind("change:first_name", this.subRender, this);
        this.model.bind("change:last_name", this.subRender, this);

        // Step 2, render my own view
        this.render();

        // Step 3/4, create the children and assign elements
        this.infoView = new InfoView({el: "#info", model: this.model});
        this.phoneListView = new PhoneListView({el: "#phone_numbers", model: this.model});
    },
    render: function() {
        // Render my template
        this.$el.html(this.template());

        // Render the name
        this.subRender();
    },
    subRender: function() {
        // Set our name block and only our name block
        $("#name").html("Person: " + this.model.first_name + " " + this.model.last_name);
    }
});

가 의구을확수있습다니인할현ation▁of▁implement다를 구현한 수 .subRender 기여에 으로써. 변화를 구속함으로써.subRenderrender저는 전체 블록을 폭파하고 재건하는 것에 대해 걱정할 필요가 없습니다.

음의코다니드입예제▁▁the다▁example의 코드 예를 들어보겠습니다.InfoView슬라이드:

var InfoView = Backbone.View.extend({
    initialize: function() {
        // I want to re-render on changes
        this.model.bind("change", this.render, this);

        // Render
        this.render();
    },
    render: function() {
        // Just render my template
        this.$el.html(this.template());
    }
});

구속력은 여기서 중요한 부분입니다.를 걸 걱정할 필요가 없습니다.render에 영향을 주지 렌더링됩니다.모델이 변경되면 이 블록은 다른 뷰에 영향을 주지 않고 다시 렌더링됩니다.

PhoneListView는 과유것할입다니사다음▁the▁to와 유사할 입니다.ParentView당신은 단지 두 가지 모두에서 조금 더 논리가 필요할 것입니다.initialization그리고.render컬렉션을 처리하는 함수입니다.컬렉션을 처리하는 방법은 실제로 사용자에게 달려 있지만 적어도 컬렉션 이벤트를 듣고 렌더링 방법(추가/제거 또는 전체 블록 재렌더링)을 결정해야 합니다.개인적으로 전체 보기를 다시 렌더링하는 것이 아니라 새 보기를 추가하고 이전 보기를 제거하는 것을 좋아합니다.

PhoneView일 할것다니입과 거의 입니다.InfoView관심 있는 모델의 변화만 듣습니다.

이것이 조금이나마 도움이 되었기를 바라며, 혼란스럽거나 충분히 상세하지 않은 것이 있으면 알려주시기 바랍니다.

이것이 당신의 질문에 직접적으로 답하는지는 모르겠지만, 저는 이것이 관련이 있다고 생각합니다.

http://lostechies.com/derickbailey/2011/10/11/backbone-js-getting-the-model-for-a-clicked-element/

제가 이 기사를 작성하는 맥락은 물론 다르지만, 제가 제시하는 두 가지 해결책은 각각의 장단점과 함께 여러분이 올바른 방향으로 나아갈 수 있도록 해야 한다고 생각합니다.

제가 보기에는 어떤 종류의 플래그를 통해 초기 설정과 이후 설정을 구분하는 것이 세상에서 가장 나쁜 생각으로 보이지 않습니다.이를 깨끗하고 쉽게 하려면 백본(기본) 보기를 확장하는 고유한 보기에 플래그를 추가해야 합니다.

데릭과 마찬가지로, 저는 이것이 당신의 질문에 직접적으로 대답하는지 완전히 확신할 수 없지만 적어도 이 맥락에서 언급할 가치가 있다고 생각합니다.

참고:백본에서 이벤트 버스 사용

Kevin Peel은 훌륭한 답변을 제공합니다 - 여기 mytl;dr 버전이 있습니다.

initialize : function () {

    //parent init stuff

    this.render(); //ANSWER: RENDER THE PARENT BEFORE INITIALIZING THE CHILD!!

    this.child = new Child();
},

저는 이런 관점들 사이의 결합을 피하려고 노력하고 있습니다.제가 주로 하는 방법은 두 가지입니다.

라우터 사용

기본적으로 라우터 기능을 통해 상위 및 하위 보기를 초기화할 수 있습니다.따라서 보기는 서로에 대한 정보가 없지만 라우터가 모두 처리합니다.

두 뷰에 동일한 엘 전달

this.parent = new Parent({el: $('.container-placeholder')});
this.child = new Child({el: $('.container-placeholder')});

둘 다 동일한 DOM에 대한 지식을 가지고 있으며, 원하는 대로 주문할 수 있습니다.

제가 하는 일은 각 아이들에게 정체성을 부여하는 것입니다(백본은 이미 당신을 위해 그렇게 했습니다: cid).

컨테이너가 렌더링을 수행할 때 'cid' 및 'tagName'을 사용하면 모든 자식에 대한 자리 표시자가 생성되므로 템플릿에서 자식은 컨테이너가 배치할 위치를 알지 못합니다.

<tagName id='cid'></tagName>

사용할 수 있는 것보다

Container.render()
Child.render();
this.$('#'+cid).replaceWith(child.$el);
// the rapalceWith in jquery will detach the element 
// from the dom first, so we need re-delegateEvents here
child.delegateEvents();

지정한 자리 표시자는 필요하지 않으며 컨테이너는 하위 DOM 구조가 아닌 자리 표시자만 생성합니다.Cotainer 및 Children은 여전히 한 번만 자체 DOM 요소를 생성합니다.

다음은 하위 뷰를 생성하고 렌더링하기 위한 가벼운 믹스인으로, 이 스레드의 모든 문제를 해결한다고 생각합니다.

https://github.com/rotundasoftware/backbone.subviews

이 플러그에서 사용하는 방법은 상위 뷰가 처음 렌더링된 후 하위 뷰를 만들고 렌더링하는 것입니다.그런 다음 상위 뷰의 후속 렌더링 시 $. 하위 뷰 요소를 분리하고 상위 뷰를 다시 렌더링한 다음 해당 위치에 하위 뷰 요소를 삽입하고 다시 렌더링합니다.이러한 방식으로 하위 뷰에서는 객체가 후속 렌더링 시 재사용되므로 이벤트를 다시 위임할 필요가 없습니다.

컬렉션 뷰(컬렉션의 각 모델이 하나의 서브뷰로 표현되는 경우)의 경우는 상당히 다르며, 제가 생각하는 독자적인 토론/해결책이 가치가 있습니다.이 경우에 대한 가장 일반적인 해결책은 마리오네트의 Collection View입니다.

편집: 컬렉션 뷰의 경우, 클릭 및/또는 끌어서 놓기를 통해 재주문을 수행할 모델을 선택해야 하는 경우에는 이보다 UI에 중점을 둔 구현을 확인할 수도 있습니다.

언급URL : https://stackoverflow.com/questions/9337927/how-to-handle-initializing-and-rendering-subviews-in-backbone-js

반응형