2012-06-25 1 views
20

Используя Магистраль и марионетку, я создал новый макет, который входит в основной контент div на моей странице. Раскладка выглядит следующим образом:Дополнительные обертки в макете и марионетке

<div id='dash-sidebar'> 
    <div id='dash-profile'></div> 
    <div id='dash-nav'></div> 
</div> 
<div id='dash-content'></div> 

Вопрос заключается в том, что, когда я сделать макет, Backbone автоматически оборачивает его в DIV, прежде чем положить его в основной контент DIV так:

<div id='main-content'>  
    <div> 
    <div id='dash-sidebar'> 
     <div id='dash-profile'></div> 
     <div id='dash-nav'></div> 
    </div> 
    <div id='dash-content'></div> 
    </div> 
</div> 

Я знаю, что я могу изменить элемент с tagName, но можно ли вообще обойти шаблон шаблоном и просто вставить его прямо в основной контент div на странице?

ответ

13

Каждый вид Backbone View должен быть представлен одним элементом. В вашем первом блоке HTML есть два элемента, поэтому он не может быть представлен представлением без предварительной упаковки его в внешний div.

Не могли бы вы реорганизовать свой макет, чтобы включить в него область main-content? Тогда макет el будет соответствовать всему внешнему div.

Еще одна вещь, которую следует попробовать использовать с помощью метода Backbone.View setElement(), чтобы переопределить создание внешнего div и вручную ввести HTML-код, который вы хотите для элемента в представлении.Что-то вроде:

onRender: function() { 
    this.setElement(/* the HTML you want for your layout */); 
} 

Я не уверен, как это будет работать, если вы прошли в HTML, который имел два родительских элементов, а не только один, однако.

+1

Есть ли способ марионетки для этого? Предпочтительно, я думаю, было бы неплохо использовать атрибут «template» – streetlight

+0

Отлично. Мне очень не нравятся все те другие ответы, которые я вижу, чтобы манипулировать DOM для решения этой проблемы. Почему, когда вы можете просто setElement()? – trusktr

6

UPDATE: Marionette.Layout является продолжение зрения Backbone, так что это нормальное поведение, см магистральных документаций:

Свойства «эль» ссылается на объекте DOM, созданном в браузере. Каждый вид Backbone.js имеет свойство «el», и если он не определен, Backbone.js построит свой собственный, который является пустым элементом div.

Так что мой предыдущий ответ не имел ничего общего с вашей проблемой, извините.

Update:

Найден issue 546 в Backbone GitHub по этому вопросу (которым был закрыт, как wontfix), jashkenas отправил этот комментарий, чтобы объяснить, почему это не так легко реализовать:

Большая часть преимущество использования Backbone Views заключается в том, что у них есть свой элемент, доступный во все времена - независимо от независимо от того, был ли обработан шаблон (многие представления имеют несколько шаблонов ) - независимо от того, присутствует ли вид в DOM или нет.

Это позволяет вам создавать и добавлять виды в DOM, затем рендерить и быть уверенным, что все ваши события связаны правильно (потому что они делегированы с view.el).

Если вы можете прийти с хорошей стратегией, позволяющей вид иметь «полные» шаблоны, сохраняя при этом вышеуказанные характеристики ... тогда давайте говорить об этом - но это должно позволить корневой элемент существует без необходимости отображать содержимое шаблона (что может быть зависит от данных, которые могут не появиться дольше), и он должен позволить виду легко иметь несколько шаблонов.

+1

Нет кубиков на любом из способов. Установка идентификатора в соответствие с родительским элементом просто добавляет один и тот же идентификатор в div обертки, поэтому у вас есть два div с одинаковым идентификатором. Второй метод не может отображать содержимое. Я попробовал как $ ('# main-content'), так и '# main-content' без везения. Любые другие идеи? –

+0

Возможно, вы могли бы взглянуть на регионы, взглянуть на [этот пост] (http://stackoverflow.com/a/10521940/984265) – marcoo

10

EDIT3: Внимание! Этот ответ может быть устаревшим. Я получил комментарий, что этот ответ больше не работает, и у меня не было времени для расследования (я лично не использую этот метод).

Я хотел бы использовать Twitter/Bootstrap в моей библиотеке UI и возникли некоторые проблемы с моделированием таблицы из-тегов по умолчанию обертывания (конкретно <div> между моими <tbody> и моими <tr> с).

После некоторого рытья я нашел что-то в документах Marionette на Region около how the View attaches the el. Backbone builds the el из различных атрибутов View и сохраняет встроенный элемент в актуальном состоянии, чтобы его можно было визуализировать в любое время. Поэтому я решил, что если view.el является родительским, почему бы просто не использовать содержимое HTML? Marionette также предоставляет способ: create a custom Region

Мне удалось запустить все, создав пользовательский Region с переопределенной функцией open. Таким образом, я могу указать, какие области я хочу обернуть тегом, а те, которые у меня нет. В следующем примере фрагмента я создаю свой собственный неинтегрирующий Region (NowrapRegion) и использую его в своих Layout (MyLayout) для моих <tbody> (виды, которые я передаю в своей реальной программе, создают <tr>).

var NowrapRegion = Marionette.Region.extend({ 
    open: function(view){ 
    this.$el.html(view.$el.html()); 
    } 
}); 

var MyLayout = Marionette.Layout.extend({ 
    template: templates.mylayout, 
    regions: { 
    foo: '#foo', 
    columns: '#columns', //thead 
    rows: { selector: '#rows', regionType: NowrapRegion } //tbody 
    } 
}); 

BOOM! Обертывание, когда я этого хочу, и нет, когда я этого не делаю.

EDIT: Это, кажется, влияет на events, применяемый на уровне *View. Я еще не изучил его, но предупреждаю, что они, похоже, не срабатывают.

Является ли это «правильным» способом сделать это или нет, я не уверен. Я бы приветствовал любые отзывы от @ derick-bailey, если он это увидит.

EDIT2: @ chris-neale предложил следующее, я еще не подтвердил это, но кажется, что это звучит. Благодаря!

Вместо того, чтобы скопировать HTML в представлении, используя глубокий клон на дочерних узлов будут поддерживать события и данные.

var NowrapRegion = Marionette.Region.extend({ 
    open: function(view){ 
    view.$el.children().clone(true).appendTo(this.$el); 
    } 
}); 
+0

Бум действительно! Я мог бы поцеловать тебя. –

+2

Разве это не должно быть частью марионетки? Я имею в виду, что ItemViews должны повторно использовать div, используемые только для выбора регионов. –

+0

Я не согласен, это наверняка сделает мои взгляды намного менее подробными. В конце концов я только что закончил с потоком и структурировал свои HTML-шаблоны, чтобы работать с поведением по умолчанию. Это было не так плохо. – clayzermk1

1

Я хотел достичь в значительной степени то же самое. Я хотел бы иметь все разметки HTML в моих шаблонах и позволить Backbone делать все остальное. Поэтому я написал следующий фрагмент, который удаляет дополнительный «div».

Сначала вы устанавливаете tagName на «обнаружение», а затем после первого рендера вы обнаруживаете tagName первого элемента внутри вашего представления. Очевидно, что это работает только тогда, когда вы предоставляете свою собственную оболочку в своем шаблоне.

// Single table row inside tbody 
tableRowView = Backbone.Marionette.ItemView.extend({ 
    tagName: 'detect', 
    template: function(data) { 
    return Handlebars.templates['tablerow/single'](data); 
    }, 
    onRender: function() { 
    if (this.tagName == 'detect') 
     this.tagName = this.$el.children().first().prop('tagName').toLowerCase(); 
    this.setElement(this.$el.children(this.tagName)); 
    var $parent = this.$el.parent(this.tagName); 
    if ($parent.length) { 
     this.$el.detach(); 
     this.$el.insertAfter($parent); 
     $parent.remove(); 
    } 
    }, 
    modelEvents: { 
    "change": "render" 
    } 
}); 

Шаблон:

<tr> 
    <td>{{artist}}</td> 
    <td>{{title}}</td> 
    <td>{{length}}</td> 
</tr> 

Однако, я просто играл с ним немного - если кто-то видит какие-то проблемы, что такой подход может привести к (производительность, память, зомби и т.д.) I» d быть очень открытым, чтобы узнать о них.

Кстати, это, вероятно, может быть легко упаковано в плагин.

+0

Вы все еще используете его, и у вас возникли проблемы? Это решение довольно интересно, но мне интересно его надежность. Он работает до сих пор, хотя, THX! – alxscms

+0

Почему бы вам не просто сделать tagName: 'tr', а затем удалить обертку из вашего шаблона? Если вам нужно добавить классы или атрибуты в строку, просто добавьте их через свойство атрибутов Backbone.View. –

Смежные вопросы