所以我使用的是Backbone.js,在我的一個主要視圖中,我遇到了一個非常奇怪的錯誤,我不能爲我的生活弄清楚如何解決。Javascript中的點擊綁定問題
該視圖看起來像新的Twitter佈局。它接收一組對象,其中每個對象都描述一個集合並查看對該集合起作用的元素。每個集合都由視圖中的一個選項卡表示。我的視圖上的render()方法使用此數組集合對象,清除tabContainer DOM元素(如果它尚未爲空),呈現選項卡,然後將事件綁定到每個選項卡。
現在在我的代碼中,我有方法來呈現選項卡和方法來按順序將點擊處理程序綁定到這些選項卡。這在第一次執行render()時正常工作,但在隨後的render()調用中,click處理程序未被綁定。下面是相關的代碼片段:
initialize: function() {
// Context on render(), _addAllTabs and _bindTabEvents is set correctly to 'this'
_.bindAll(this, 'render', 'openModel', 'closeModel', 'isOpen', 'addAllModels', '_switchTab',
'addOneModel', '_addTab', '_removeTab', '_addAllTabs', '_loadCollection',
'_renderControls', '_setCurrentCollection', '_loadModels', '_bindTabEvents');
this.template = JST['ui/viewer'];
$(this.el).html(this.template({}));
// The tabContainer is cached and always available
this.tabContainer = this.$("ul.tabs");
this.collectionContainer = this.$("#collection_container");
this.controlsContainer = this.$("#controls");
this.showMoreButton = this.$("#show_more_button");
},
render: function(collections, dashboard) {
// If _bindTabEvents has been called before, then this.tab exists. I
// intentionally destroy this.tabs and all previously bound click handlers.
if (this.tabs) this.tabContainer.html("");
if (collections) this.collections = collections;
if (dashboard) this.$("#dashboard").html(dashboard.render().el);
// _addAllTabs redraws each of the tabs in my view from scratch using _addTab
this._addAllTabs();
// All tabs *are* present in the DOM before my _bindTabEvents function is called
// However these events are only bound on the first render and not subsequent renders
this._bindTabEvents();
var first_tab = this.collections[0].id;
this.openTab(first_tab);
return this;
},
openTab: function (collectionId, e) {
// If I move _bindTabEvents to here, (per my more thorough explanation below)
// my bug is somehow magically fixed. This makes no friggin sense.
if (this.isTabOpen(collectionId)) return false;
this._switchTab(collectionId, e);
},
_addAllTabs: function() {
_.each(this.collections, this._addTab);
},
_bindTabEvents: function() {
this.tabs = _.reduce(_.pluck(this.collections, "id"), _.bind(function (tabEvents, collectionId) {
var tabId = this.$("#" + collectionId + "_tab");
tabEvents[collectionId] = tabId.click(_.bind(this._switchTab, this, collectionId));
return tabEvents
}, this), {});
},
_addTab: function(content) {
this.tabContainer.append(
$('<li/>')
.attr("id", content.id + "_tab")
.addClass("tab")
.append($('<span/>')
.addClass('label')
.text(content.name)));
//this._loadCollection(content.id);
this.bind("tab:" + content.id, this._loadCollection);
pg.account.bind("change:location", this._loadCollection); // TODO: Should this be here?
},
etc..
正如我所說的,這裏的render()方法的工作,但只在第一次左右。奇怪的是,如果我招行this._bindTabEvents();
並使其成爲openTab(第一行)方法就像下面的代碼片段,那麼整個事情完美的作品:
openTab: function (collectionId, e) {
this._bindTabEvents();
if (this.isTabOpen(collectionId)) return false;
this._switchTab(collectionId, e);
},
當然,這行代碼沒有業務在該方法的,但它確實使整個事情做工精細,這使我問,爲什麼在那裏工作,但沒有像這樣連續工作:
this._addAllTabs();
this._bindTabEvents();
這是沒有意義的,我因爲如果我把它放在這行之後,它也不起作用:
var first_tab = this.collections[0].id;
即使這基本上與執行順序有關的工作相同。
有沒有人有任何想法我做錯了什麼,我應該怎麼做才能做到這一點(在行爲和編碼風格方面)?
它是如何「不工作」?瀏覽器說什麼?什麼樣的例外?在哪條線上?是否有錯誤? – Rudie 2011-04-25 00:36:17
這是奇怪的部分。沒有例外或沒有。一切都打印出來控制檯就好了。但是當我點擊標籤沒有事件被解僱。第一次和後續時間之間的clickbind的console.log打印輸出的唯一區別在於,jquery對象數組中的元素名稱在第一次被灰顯,隨後他們將元素名稱打印成黑色。 – 2011-04-25 05:08:22