在页面更改时,在列表视图项和相应的详细视图之间保持新引用的最直接方法是重新渲染详细视图。但我假设这个选项在您的项目范围内是不可接受的。
当我有在逻辑上分离的视图中形成关系的任务时,我经常做的是使用监听器。只要视图共享一个唯一标识符(例如,它们都共享一个模型,或至少相同的模型 ID),我总是可以发送一条消息,该消息将到达我感兴趣的视图。
为此,您需要一个集中的事件中心,使用 Backbone 很容易生成。在某些适当的全局变量中(例如,MyApp
),我们只需执行以下操作:
MyApp.EventBus = _.extend({}, Backbone.Events);
设置详细视图
在详细视图初始化函数上,我将删除此侦听器,
initialize: function () {
// Listen to a toggle visibility on this view
this.listenTo(MyApp.EventBus, 'detail-view:toggle-view', toggleView);
},
toggleView: function (id) {
if (this.model.id == id) {
// Show this view if I have the passed id
this.$el.show()
// Notify the parent list item view that its detail view exists
MyApp.EventBus.trigger('detail:view:exists', true);
} else {
// Hide all other views
this.$el.hide();
}
},
changeName: function () {
// logic that parses DOM user input to
// local variable name
// We now trigger an event 'detail-view:change:name', and we send as
// parameters our model's id and the new name
MyApp.EventBus.trigger('detail-view:change:name', this.model.id, name);
}
设置列表项视图
列表项视图将希望监听名称更改(或您希望列表项知道的详细视图中的任何其他模型属性)。所以我们将为 'detail-view:change:name' 事件设置一个处理程序。
我们还想连接我们的点击处理程序来切换列表项详细视图的可见性。棘手的部分是处理尚未呈现视图的事件(我假设您延迟加载详细视图)。detail:view:exists
因此,我们为细节视图在捕获事件时触发的事件设置了第二个侦听器detail-view:toggle-view
。如果我们没有detail:view:exists
及时从目标详细视图中听到事件(我使用的是 100 毫秒,但您可以根据自己的需要进行调整),然后我们渲染视图。
initialize: function () {
// Listen to when the detail associated with this list item changes
// the the list item name
this.listenTo(MyApp.EventBus, 'detail-view:change:name', onNameChange);
// Set a property in this view if its detail view exists
this.listenTo(MyApp.EventBus, 'detail:view:exists',
_.bind(function () { this.detailViewExists = true; }, this));
// Create a debounced function that tests whether this view's
// detail view exists
_.debounce(_.bind(this.handleViewState, this), 100);
},
events {
click: 'toggleDetailView'
},
toggleDetailView: function (id) {
MyApp.EventBus.trigger('detail-view:toggle-view', this.model.id);
this.handleViewState();
},
// Debounced function that will wait 100ms asynchronously for the
// detail view to respond. If the detailViewExists bit is not set to true
// then we assume the view does not exist and we render it
handleViewState: function () {
if (!this.detailViewExists)
// The view does not exist, render and attach the view
// Set the bit to false to allow testing in the event that the detail view
// is destroyed in the future
this.detailViewExists = false;
},
changeName: function (id, newname) {
if (this.model.id == id) {
// Change the name of this list item view
this.$('.item-name').text(newname);
}
外卖
现在,这两个不同视图之间的引用是共享的唯一标识符。因为,根据设计,这两个标识符在其范围内是唯一的,并且不应更改,并且假设详细视图已被渲染并附加到 DOM,那么无论渲染其状态如何,列表项视图都将始终能够通信及其详细视图。