2013-05-31 18 views
9

Tôi có chế độ xem bố cục với một khu vực, trong khu vực đó, tôi có chế độ xem mục kích hoạt sự kiện nhưng có vẻ như nó không được hiển thị ở chế độ xem bố cục. Tôi đang làm điều gì đó sai hay là hành vi được thiết kế này? Tôi cho rằng tiền tố itemview không được thêm vì chế độ xem gốc không phải là chế độ xem bộ sưu tập? Dù bằng cách nào, sự kiện này không bao giờ bị ảnh hưởng đến chế độ xem bố cục.Sự kiện bong bóng rối từ itemview đến bố cục bố cục gốc?

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:

Xem fiddle này http://jsfiddle.net/7ATMz/11/ tôi quản lý để có được cái nhìn bố trí để lắng nghe những sự kiện con nhưng tôi phải dây nó lên bên ngoài của quan điểm bố trí riêng của mình và phá vỡ đóng gói. Tôi có thể làm điều này trong chế độ xem bố cục không?

Cảm ơn,

Jon

Trả lời

0

Tại sao không chỉ cho phép những sự kiện click vào bong bóng lên hệ thống phân cấp DOM và xử lý nó theo quan điểm bố trí của bạn? Một cái gì đó như thế này (fiddle 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

này dường như không hoạt động nếu tôi nâng cao sự kiện từ chế độ xem trong vùng con bố cục? – Jon

+0

Xin lỗi, đó là một chút đoán thật sự. Sự kiện nhấp chuột sẽ làm bong bóng phân cấp DOM lên chế độ xem bố cục của bạn để bạn có thể nắm bắt nó trong Bố cục của mình bằng cách sử dụng đối tượng sự kiện thông thường. –

+0

Bạn có thể đặt cùng một ví dụ http://jsfiddle.net đơn giản không? –

10

Kích hoạt không hoàn toàn hoạt động như thế: bố cục của bạn đang sử dụng sai. Trình kích hoạt là một sự thuận tiện để tăng tín hiệu sự kiện cho một tương tác nhất định (ví dụ: nhấp chuột).

Điều bạn muốn là sử dụng triggerMethod (https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.functions.md#marionettetriggermethod) để kích hoạt chức năng trong bố cục của bạn. Xem http://jsfiddle.net/ZxEa5/ Về cơ bản, bạn muốn điều này trong chức năng show của bạn:

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

Và trong cách bố trí của bạn:

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

tổ chức sự kiện chỉ xảy ra bọt Automagically với bộ sưu tập quan điểm tổng hợp bởi vì họ đang liên kết chặt chẽ với mục của họ? lượt xem. Nếu bạn muốn bố trí theo dõi một trong các chế độ xem con của nó, bạn cần phải tự thiết lập bố cục đó.

Plug Shameless: nếu bạn muốn tìm hiểu thêm về cách cấu trúc và dọn dẹp mã của bạn với Marionette, bạn có thể xem cuốn sách của tôi (https://leanpub.com/marionette-gentle-introduction), nơi loại khái niệm này (và các ứng dụng của nó) được giải thích chi tiết hơn.

+1

Theo ý kiến ​​khiêm tốn của tôi, nó trực quan hơn nếu bố cục sẽ xử lý tất cả các sự kiện sôi nổi từ các con của nó một cách tự động. Nếu không, tôi sẽ ngoại trừ một lỗi ngoại lệ hoặc ít nhất một cảnh báo rằng một sự kiện đã không được xử lý ở tất cả. Không ai trong số này xảy ra với phiên bản marionette mới nhất –

1

Tôi đã triển khai giải pháp cho một vấn đề tương tự như sau. Trước tiên, tôi đã viết một phương pháp mới ngay vào nguyên mẫu 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)) 
} 

Đó sẽ gọi thường xuyên triggerMethod từ rối hai lần: một lần với tên sự kiện của bạn vì nó được thiết kế để được xử lý, và một thứ hai có thể dễ dàng nhận ra bởi các khung nhìn chuyên biệt, được chỉ định cho các sự kiện bong bóng lên.

Sau đó, bạn sẽ cần các chế độ xem chuyên biệt và sự kiện bong bóng đó có nghĩa là được làm sôi nổi. Bạn phải cẩn thận không gửi các sự kiện như close (hoặc bất kỳ sự kiện rối loạn nào) thay mặt cho các chế độ xem khác, vì điều đó sẽ gây ra tất cả các hành vi không thể đoán trước trong Khu vực và Chế độ xem. Hậu tố :bubble cho phép bạn dễ dàng nhận ra những gì có nghĩa là bong bóng.Quan điểm bọt có thể trông như thế này:

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

Điều cuối cùng bạn cần phải chắc chắn là để có thể sự kiện bong bóng giữa các vùng (ví Layouts và mô-đun với các nhà quản lý khu vực tùy chỉnh). Điều đó có thể được xử lý với show văn kiện từ một khu vực, như thế này:

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

Phần cuối cùng là làm cho một cái gì đó thực sự bong bóng lên, mà có thể dễ dàng xử lý bởi các bubbleMethod phương pháp mới:

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

Bây giờ bạn có thể xử lý các sự kiện sôi nổi từ bất kỳ vị trí nào trong mã của bạn, nơi bạn có thể truy cập một phiên bản BubblingLayout.

4

tôi khuyên bạn nên sử dụng Backbone.Courier cho loại hình này cần: https://github.com/rotundasoftware/backbone.courier

+3

Đi xa hơn ví dụ này, bạn có khuyên bạn nên sử dụng Courier trên những gì đã được triển khai trong Marionette cho sự kiện bubbling từ ItemViews đến CollectionView cha mẹ của họ? – backdesk

7

Tôi không chắc chắn khi tính năng rối này đã được giới thiệu, nhưng một giải pháp đơn giản hơn nhiều sẽ được sử dụng childEvents băm: http://marionettejs.com/docs/v2.4.1/marionette.layoutview.html#layoutview-childevents

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

Bạn cũng có thể trực tiếp liên kết các sự kiện con để một chức năng bên ngoài của LayoutView, nếu nó có ý nghĩa hơn, như thế này:

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

Đã thử và không hoạt động. Nó đã làm việc cho bạn? Tôi đã phải nói rõ ràng cách bố trí để 'listenTo' con của nó. Ví dụ: 'this.listenTo (this.announcementRegion.currentView," poisonpill ",() => { this.announcementRegion.empty() });' –

+0

Không, nó hoạt động tốt cho tôi, tôi đã thử điều này cho CollectionView, LayoutView và CompositeView. – kprist

+0

Đây là một giải pháp tuyệt vời, cập nhật! – Seth