2013-05-31 1 views
9

У меня есть вид макета с областью, в этом регионе. У меня есть представление элемента, которое запускает событие, но оно, похоже, не пузырится до вида макета. Я что-то делаю неправильно или это настроенное поведение? Я предполагаю, что префикс itemview не добавляется, поскольку родительское представление не является представлением коллекции? В любом случае это событие никогда не пузырится на макет.Событие Marionette bubble от itemview до родительского макета?

layoutView = Marionette.Layout.extend({ 
     template: "#layout-template", 
     regions: { 
      titleRegion: "#job-title-region" 
     }, 
     triggers: { 
      "save:clicked" : "onSaveClicked" 
     }, 
     onSaveClicked: function (args) { 
      alert('Clicked'); 
     } 
    }); 

childview = Marionette.ItemView.extend({ 
     template: "#child-template", 
     triggers: { 
      "click .js-save": "save:clicked" 
     } 
    }); 

UPDATE:

Смотрите эту скрипку http://jsfiddle.net/7ATMz/11/ мне удалось получить вид макета для прослушивания события ребенка, но я должен подключить его за пределы самого макете и нарушить герметизацию. Могу ли я сделать это в макете в любом случае?

Спасибо,

Jon

ответ

0

Почему просто не позволить событие щелчка на пузырек вверх по иерархии DOM и обрабатывать его в режиме разметки? Что-то вроде этого (скрипка here):

var MainView = Marionette.Layout.extend({ 
    template: "#layout-template", 
    regions: { 
     childRegion: "#childRegion" 
    }, 
    events: { 
     'click #btn': 'handleButtonClick' 
    }, 
    handleButtonClick: function() { 
     alert('btn clicked in child region and bubbled up to layout'); 
    } 
}); 

var ChildView = Marionette.ItemView.extend({ 
    template: "#child-template" 
    /* 
    triggers: { 
     "click #btn": "btn:clicked" 
    }*/ 
}); 
+0

это похоже, не работает, если я поднимаю событие из представления в дочернем регионе макетов. – Jon

+0

Извините, это было немного догадаться. Событие клика должно так или иначе вызывать иерархию DOM в вашем макете, чтобы вы могли поймать его в своем макете с помощью обычного объекта событий. –

+0

Не могли бы вы собрать простой пример http://jsfiddle.net? –

10

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

Вы хотите использовать triggerMethod (https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.functions.md#marionettetriggermethod), чтобы вызвать функцию в вашем макете. См http://jsfiddle.net/ZxEa5/ В принципе, вы хотите это в show функции:

childView.on("btn:clicked", function(){ 
    layout.triggerMethod("childView:btn:clicked"); 
}); 

И в макете: кипящий

onChildViewBtnClicked: function(){ 
    https://leanpub.com/marionette-gentle-introduction 
}); 

События происходит только автомагический с коллекцией составных видов, потому что они тесно связаны с их товаром? Просмотры. Если вы хотите, чтобы макет контролировал одно из своих дочерних представлений, вам нужно настроить это самостоятельно.

Бесстыдный штекер: если вы хотите узнать больше о том, как структурировать и очистить свой код с помощью Marionette, вы можете проверить мою книгу (https://leanpub.com/marionette-gentle-introduction), где этот вид концепции (и ее приложения) объясняется более подробно.

+1

По моему скромному мнению, более интуитивно, если макет будет обрабатывать все пузырьковые события от своих детей автоматически. В противном случае я хотел бы исключить ошибку исключения или хотя бы предупреждение о том, что событие вообще не обрабатывалось. Ничего из этого не случилось с последней версией марионетки –

1

Я реализовал решение для аналогичной проблемы следующим образом. Во-первых, я написал новый метод прямо в прототипе Marionette.View:

Marionette.View.prototype.bubbleMethod = function() { 
    var args = _.toArray(arguments) 
    var event = args.shift() 
    var bubble = event + ':bubble' 
    this.triggerMethod.apply(this, [ event ].concat(args)) 
    this.triggerMethod.apply(this, [ bubble ].concat(args)) 
} 

Это будет вызывать регулярные triggerMethod из кукольного дважды: один раз с именем события, как оно предназначено быть обработаны, и второй, который легко узнаваемы специализированными представлениями, предназначенными для пузырьков событий.

Тогда вам понадобятся такие специализированные виды и события пузырей, которые должны быть пузырящимися. Вы должны быть осторожны, чтобы не отправлять события, такие как close (или любые события Marionette вообще) в интересах других видов, потому что это вызовет всевозможные непредсказуемые поведения в регионах и представлениях. Суффикс :bubble позволяет вам легко распознать, что означает пузырь.Вид пузыриться может выглядеть следующим образом:

var BubblingLayout = Marionette.Layout.extend({ 
    handleBubbles: function (view) { 
     var bubble = /:bubble$/ 
     this.listenTo(view, 'all', function() { 
      var args = _.toArray(arguments) 
      var event = args.shift() 
      if (event.match(bubble)) { 
       event = event.replace(bubble, '') 
       this.bubbleMethod.apply(this, [ event ].concat(args)) 
      } 
     }, this) 
    } 
}) 

Последнее, что вам нужно, чтобы убедиться, чтобы быть в состоянии пузырь событий в разных регионах (для макетов и модулей с менеджерами пользовательского региона). Это могут быть обработаны с show отправок событий из региона, как это:

var BubblingLayout = Marionette.Layout.extend({ 
    regions: { 
     sidebar: '#sidebar' 
    }, 
    initialize: function() { 
     this.sidebar.on('show', this.handleBubbles, this) 
    }, 
    handleBubbles: function (view) { 
     var bubble = /:bubble$/ 
     this.listenTo(view, 'all', function() { 
      var args = _.toArray(arguments) 
      var event = args.shift() 
      if (event.match(bubble)) { 
       event = event.replace(bubble, '') 
       this.bubbleMethod.apply(this, [ event ].concat(args)) 
      } 
     }, this) 
    } 
}) 

Последняя часть, чтобы сделать что-то на самом деле пузыриться, который легко обрабатывается с помощью нового bubbleMethod метода:

var MyView = Marionette.ItemView.extend({ 
    events: { 
     'click': 'clickHandler' 
    }, 
    clickHandler: function (ev) { 
     // do some stuff, then bubble something else 
     this.bubbleMethod('stuff:done') 
    } 
}) 

var BubblingLayout = Marionette.Layout.extend({ 
    regions: { 
     sidebar: '#sidebar' 
    }, 
    initialize: function() { 
     this.sidebar.on('show', this.handleBubbles, this) 
    }, 
    onRender: function() { 
     var view = new MyView() 
     this.sidebar.show(view) 
    }, 
    handleBubbles: function (view) { 
     var bubble = /:bubble$/ 
     this.listenTo(view, 'all', function() { 
      var args = _.toArray(arguments) 
      var event = args.shift() 
      if (event.match(bubble)) { 
       event = event.replace(bubble, '') 
       this.bubbleMethod.apply(this, [ event ].concat(args)) 
      } 
     }, this) 
    } 
}) 

Теперь вы можете обрабатывать пузырьковые события из любого места вашего кода, где вы можете получить доступ к экземпляру BubblingLayout.

4

Я рекомендую использовать Backbone.Courier для этого типа потребности: https://github.com/rotundasoftware/backbone.courier

+3

Выйдя за пределы этого примера, вы бы посоветовали использовать Courier над тем, что уже реализовано в Marionette для пузырящихся событий от ItemViews до их родительского CollectionView? – backdesk

7

я не уверен, когда эта функция марионеток была введена, но гораздо более простое решение было бы с помощью childEvents хэш: http://marionettejs.com/docs/v2.4.1/marionette.layoutview.html#layoutview-childevents

... 
childEvents: { 
    "save:clicked" : "onSaveClicked" 
}, 
... 

Вы также можете напрямую связать событие ребенка к функции вне LayoutView, если это имеет смысл, как это:

layout.on('childview:save:clicked', function(childView) { 
    alert('clicked'); 
} 
+0

Пробовал и не работал. Это сработало для вас? Мне пришлось явно указать макету «слушать» его ребенка. Например: 'this.listenTo (this.announcementRegion.currentView," poisonpill ",() => { this.announcementRegion.empty() });' –

+0

Нет, это работает для меня просто отлично, я пробовал это для CollectionView, LayoutView и CompositeView. – kprist

+0

Это отличное, современное решение! – Seth