我试图扩展我的Backbone.View类。 最初我提出了创建自己的界面的想法,以简化删除childViews所需的代码量。
基本上,一个数组和一些方法迭代数组上的每个视图,为每个视图调用remove。这对列表等事情特别有用。
然后我尝试了类似的东西,并意识到从类创建的对象在其属性上共享相同的实例。
Backbone.SuperView = Backbone.View.extend({
childViews: ['global']
})
var App_View = Backbone.SuperView.extend({
initialize: function(options){
this.childViews.push(options.viewName);
console.log('app_View =>' + this.childViews);
}
})
var App2_View = Backbone.SuperView.extend({
initialize: function(options){
this.childViews.push(options.viewName);
console.log('app2_View =>' + this.childViews);
}
})
new App_View({viewName: 'a'});
new App2_View({viewName: 'b'});
输出:
app_View => global ,a
app2_View => global ,a ,b
我不想在我从Backbone.SuperView创建的所有对象中使用相同的childViews实例!就像你可以想象我假装在从该类创建的所有对象中都有一个数组childViews但我有不同的内存实例,所以每个视图都有它自己的子视图。
然后我想出了以下概念,但我仍然认为这不是正确的做事方式:
我的概述课程
;(function($, _ , Backbone) {
'use strict';
Backbone.SuperView = Backbone.View.extend({
initialize: function(){
this._views = {};
this._listViews = [];
this._bindedElements = [];
_.extend(this,
{
_destoryAllViews: function(){
this._removeListViews();
this._removeViews();
this.remove();
},
// destroy a view atual e as subviews e listviews
destroy: function(options){
options = options || {};
var defaults = {timeout : 200};
if (_.isEmpty(options)){
options = defaults;
setTimeout($.proxy(function(){
this._destoryAllViews();
this._cleanExternalEventBinds();
},this), options.timeout );
} else {
this._destoryAllViews();
this._cleanExternalEventBinds();
}
},
addListView: function(view){
this._listViews.push(view);
},
// manual view cleaner
emptyListView: function(destroy){
this._removeListViews();
},
/*
views with same keys are destroyed and then assigned
*/
set: function(key, view, options){
options = options || {};
var destroy = ('destroy' in options ) ? options.destroy : true;
if (key in this._views){
this._views[key].view.destroy();
}
this._views[key] = { 'view': view, 'destroy': destroy };
return view;
},
get: function(key){
return this._views[key].view;
},
_removeViews: function(){
_.each( this._views, function( viewSettings ){
if (viewSettings.destroy){
if (viewSettings.view.destroy){
viewSettings.view.destroy();
}
}
});
},
_removeListViews: function(){
_.each( this._listViews, function( view ){
if (view.destroy){
view.destroy();
}
});
},
setEvent: function(el, eventName, callback){
var $el = $(el),
callback = (_.isFunction(callback)) ? callback : this[callback];
$el.bind(eventName + '.' + this.cid, callback);
this._bindedElements.push(el);
},
_cleanExternalEventBinds: function(){
var _that = this;
_.each(this._bindedElements, function(el){
el.off('.' + _that.cid );
});
}
});
}
});
//_.extend(Backbone.SuperView.prototype, )
return Backbone;
})($, _ , Backbone);
我的HTML
<a href="#" class="my-btn">My-btn</a>
<div class="app-placeholder"></div>
MY SCIRPT
var c = Backbone.Collection.extend({});
var C = new c([{
name: 'Frank',
age: 12
},
{
name: 'Maria',
age: 19
},
{
name: 'Richard',
age: 20
}])
var header_View = Backbone.SuperView.extend({
events: {
'click': 'log'
},
initialize: function(){
Backbone.SuperView.prototype.initialize.call(this);
this.$mybtn = $('.my-btn');
this.setEvent(this.$mybtn, 'click', function(e){
e.preventDefault();
alert('hello');
});
this.setEvent(this.$mybtn, 'click', 'innerHello')
// this.setEvent(this.$mybtn, 'click', 'log')
this.$el.append('<h1>My Header</h1>')
return this;
},
innerHello: function(e){
// e.preventDefault();
alert('hello 2');
},
log: function(){
console.log(this._bindedElements);
}
});
var item = Backbone.SuperView.extend({
template: _.template('<%= age %>||<%=name%>'),
events: {
'click': 'log'
},
initialize: function(options){
Backbone.SuperView.prototype.initialize.call(this);
this.model = options.model;
this.render();
},
render: function(){
this.$el.html('').append(this.template(this.model.toJSON()))
},
log: function(){
console.log(this._bindedElements);
}
})
var b = Backbone.SuperView.extend({
initialize: function(){
Backbone.SuperView.prototype.initialize.call(this);
this.set('myView', new header_View());
this.$el.html( '' ).append( this.get('myView').el );
this.collection = C;
this.render();
},
render: function(){
this.emptyListView();
this.addAll();
},
addAll: function(){
this.collection.forEach(function(model){
var _item = new item({model:model});
this.addListView( _item );
this.$el.append( _item.el );
},this)
}
})
var m = Backbone.View.extend({
initialize: function(){
},
})
var B = new b();
$('.app-placeholder').append(B.el);
这感觉不对,我正在寻找更加可靠的解决方案。 我是否真的必须在每个视图中调用初始值设定项?
上面的代码是这样的:
运行该脚本将呈现3个项目和标题的列表。
header_view使用我自己创建的方法将事件绑定到视图外的DOM元素
它将dom元素插入到数组中,稍后,当元素被销毁时,事件也会从该全局元素中分离,从而防止内存和事件发生。
在上述情况下,只需点击header_view就会输出_bindedElements中的有界元素,因为iniside header_View初始化我调用this.setEvent($ el,&#39; eventName&#39;,callback)
< / LI> 醇>