在传播之前使用自定义数据扩展事件
Extending an event with custom data before it propagates
我有一个在另一个视图 (OuterView
) 内呈现的 Backbone 视图 (InnerView
)。两者都包含 click
事件的事件处理程序,并且启用事件委托(默认情况下)。
我想 InnerView
在事件进一步传播之前向事件附加一些数据。但是,代码——如下所示——似乎根本不会影响 e.data
,因为它之后仍然未定义:
var InnerView = Backbone.View.extend({
events: {
"click": "onClick"
},
render: function () {
// ...
},
onClick: function (e) {
e.data = e.data || {};
e.data.myData = 123;
console.log(e.data); // Object { myData: 123 }
}
});
var OuterView = Backbone.View.extend({
events: {
"click": "onClick"
},
render: function () {
// ...
this.$el.append(new InnerView);
// ...
},
onClick: function (e) {
console.log(e.data); // undefined
}
});
我尝试阻止事件传播然后使用自定义数据重新触发它(将以稍微不同的格式存储,因为我在这里看不到将数据附加到事件对象的方法):
// alternative version of InnerView#onClick()
onClick: function (e) {
e.stopImmediatePropagation();
this.trigger('click', {myData: 123});
}
但是 OuterView
根本没有收到任何点击事件。
我该如何处理这个问题?请注意,我无法在目标视图上直接触发我的事件(或调用方法,或设置 属性),因为两者不会相互暴露(这就是为什么我决定利用事件机制)。
您不能使用 this.trigger()
,因为这是使用 Backbone 的事件 API 而不是 jQuery 的。您需要 OuterView 从 InnerView 侦听此事件,但是,正如您所说,这些视图不会相互公开。
如果您想向上发送数据 DOM,我认为您转向 jQuery's trigger 的方向是正确的。但是,我会从 InnerView 触发一个 custom 事件:
onClick: function () {
this.$el.trigger('custom', {
myData: 123
});
}
这样,点击事件传播可以正常进行,OuterView 可以专门 监听自定义事件:
events: {
"custom": "onCustom"
},
onCustom: function (e, data) {
console.log(data.myData); //123
}
此外,请注意将自定义数据作为第二个参数传递给事件处理程序的便利性。
实现此目的的一种方法是创建一个包含数据的全局可访问时间戳对象 (event.timeStamp)。您可以将对象附加到该数组 - 例如:
var eventTimestamps = {}
function someEventCallBack(e) {
if (eventTimestamps[e.timeStamp] === undefined) {
// it's a new event, attach things?
eventTimestamps[e.timeStamp] = { name: 'Bob' }
} else {
eventData = eventTimestamps[e.timeStamp]
// this event has data
if (eventData.bob !== undefined && typeof eventData.bob === 'string') {
console.log("my name is..." + bob)
}
}
}
以上内容相当笨拙。我创建了这个代码笔,它将所有这些功能简化为一个易于使用的对象,在示例中没有类型保护,这样它背后的逻辑就更清晰了。
我有一个在另一个视图 (OuterView
) 内呈现的 Backbone 视图 (InnerView
)。两者都包含 click
事件的事件处理程序,并且启用事件委托(默认情况下)。
我想 InnerView
在事件进一步传播之前向事件附加一些数据。但是,代码——如下所示——似乎根本不会影响 e.data
,因为它之后仍然未定义:
var InnerView = Backbone.View.extend({
events: {
"click": "onClick"
},
render: function () {
// ...
},
onClick: function (e) {
e.data = e.data || {};
e.data.myData = 123;
console.log(e.data); // Object { myData: 123 }
}
});
var OuterView = Backbone.View.extend({
events: {
"click": "onClick"
},
render: function () {
// ...
this.$el.append(new InnerView);
// ...
},
onClick: function (e) {
console.log(e.data); // undefined
}
});
我尝试阻止事件传播然后使用自定义数据重新触发它(将以稍微不同的格式存储,因为我在这里看不到将数据附加到事件对象的方法):
// alternative version of InnerView#onClick()
onClick: function (e) {
e.stopImmediatePropagation();
this.trigger('click', {myData: 123});
}
但是 OuterView
根本没有收到任何点击事件。
我该如何处理这个问题?请注意,我无法在目标视图上直接触发我的事件(或调用方法,或设置 属性),因为两者不会相互暴露(这就是为什么我决定利用事件机制)。
您不能使用 this.trigger()
,因为这是使用 Backbone 的事件 API 而不是 jQuery 的。您需要 OuterView 从 InnerView 侦听此事件,但是,正如您所说,这些视图不会相互公开。
如果您想向上发送数据 DOM,我认为您转向 jQuery's trigger 的方向是正确的。但是,我会从 InnerView 触发一个 custom 事件:
onClick: function () {
this.$el.trigger('custom', {
myData: 123
});
}
这样,点击事件传播可以正常进行,OuterView 可以专门 监听自定义事件:
events: {
"custom": "onCustom"
},
onCustom: function (e, data) {
console.log(data.myData); //123
}
此外,请注意将自定义数据作为第二个参数传递给事件处理程序的便利性。
实现此目的的一种方法是创建一个包含数据的全局可访问时间戳对象 (event.timeStamp)。您可以将对象附加到该数组 - 例如:
var eventTimestamps = {}
function someEventCallBack(e) {
if (eventTimestamps[e.timeStamp] === undefined) {
// it's a new event, attach things?
eventTimestamps[e.timeStamp] = { name: 'Bob' }
} else {
eventData = eventTimestamps[e.timeStamp]
// this event has data
if (eventData.bob !== undefined && typeof eventData.bob === 'string') {
console.log("my name is..." + bob)
}
}
}
以上内容相当笨拙。我创建了这个代码笔,它将所有这些功能简化为一个易于使用的对象,在示例中没有类型保护,这样它背后的逻辑就更清晰了。