JavaScript進階(二十九):DOM 的編譯(四)

如果只是到這爲止,相信大家並不會滿足,因爲這裏面還有很多的問題,那麼我們就再進一步。

現在我希望有個按鈕,可以自定義事件:

vue 裏面用的是 @,當然,我們也一定非得用 @ 嗎?

隨便,什麼都行,只不過我們現在暫時先用這個,畢竟看着習慣點。

 

前面幾篇博客,我們只是做了第一步操作,編譯了所有的模板 {{ }}。

那麼第二步,我們就還需要找到所有的事件。

當然在這,爲什麼非得弄個 @ 開頭,我們直接 click 不行嗎?

很簡單,因爲如果是 @ 開頭的話,我們就會有個標準,也就是說,我們就可以很輕鬆的來判斷它是不是個事件了,因爲只要是 @ 開頭,就說明它是個事件。

如果不加,我們判斷的還更麻煩一些,你要把所有的事件都寫出來,然後在判斷如果它等於 click 再怎麼怎麼樣,所以一般我們都是有個標誌的。

 

然後接下來,我們就找所有的事件:

當然,這裏我們可以寫成 children:

因爲事件是不是隻能往元素身上加?

如果是在一行文字裏面出現個這東西,我們是不需要響應的,因爲它就是一段文字:

所以其實我們這裏用 children 也行。

然後我們仍然做一個循環,就有了一個又一個的 child:

然後這個 child,我要做的事就非常的簡單。

我要的,是它的 attributes,這個在我們前面的博客剛好說過。

然後這個 attributes,我們也要對它做一個小小的循環,那麼得到的,就是一個又一個的 attr:

我要做的非常的簡單,就是如果 attr.name,是以 @ 開頭的,那麼我就認爲有事件:

那麼這時候我們需要知道幾件事:

第一,這個事件,它到底要去叫什麼名字。

比如是 click 事件,還是 mouseover 事件,還是別的什麼事件,你需要知道它的名字。

第二,你還需要知道,它到底要執行什麼樣的代碼。

 

那麼具體來說,怎麼做呢?

首先,別的不多管,我們就來看一看,這個 attr 的 name 和 value 分別是什麼:

那麼這時候你可以看到,就是 @click,對應的就是一個 add。

 

那麼現在這時候,我們就需要做一個事,獲取它的事件名:

那麼這時候你可以看到,我們要執行的就是 click 事件,它對應的就是執行 add 方法。

 

那麼加個 click 事件難嗎?必然不難,我們可以用 addEventListener:

那麼現在,我希望的就是,當它點擊的時候,可以把這個 arrt.value 給打印出來:

現在別的先不管,至少你可以看到,當我點擊按鈕的時候,右邊的 console,是可以出來的。

雖然它沒有真的執行什麼,但是已經有反應了。

 

然後接下來,我想換一個事件,mouseover:

你可以看到,都可以。

 

但是接下來,我們是不是真的還得執行這個 add 方法?

那麼我們是不是可以和之前一樣,用 eval?

你可以看到,報錯了,說沒有 add 這個方法,所以,我們先加上:

先不管別的,我們先確保這個 add 能出來再說。

 

既然現在所有的方法都集中在 methods 這一個地方,那麼剩下的事,是不是就變的好辦了呀。

就和前面一樣,我能不能這麼寫:

那麼現在這個 this.methods 有嗎?是沒有的。

現在的 methods 只存在於 options 裏面,所以我們還得保存所有的 methods,供後面來使用:

那麼這個東西有了之後,剩下的東西就變的異常好辦。

我現在要的,就是 this._methods 裏面的 add:

那麼我們現在不妨來試一試:

可以看到,當我們點擊時候,add 是能執行到的。

但是我這個 this.a+=6,還沒執行,怎麼辦?

 

慢慢來,首先我們這邊 eval 已經有了,說明它已經能執行到了,但是我這能就這麼寫死嗎?

肯定不行,是不是得跟前面解析模板一樣啊?我們就直接來了:

到這爲止,我們先來試試:

那麼你可以看到,掛了。

 

大家可能會奇怪,這怎麼會掛啊?

我們別急着執行,看看它拼出來的到底是什麼:

你可以看到,它拼出來的是個這玩意。

let add = add(){ },這肯定是不對的,它連 function 都不加。

那我們怎麼解決這問題?

 

其實很簡單,我們剛纔沒用這個 for 循環之前,我們是這麼寫的:

說白了,this._methods 這塊你直接寫就行,你別去動它,別把它也翻譯了。

所以這塊是定死的,你別讓它動,那麼這時候就對了嗎?

你可以看到,當我們點擊的時候,也報錯,爲什麼呀?

大家覺得 let add = this._methods[add] 這行代碼有什麼錯?

肯定有錯啊,少東西,是不是少個引號啊:let add = this._methods["add"]

 

所以我們是不是又要把 JSON.stringify 給加上了?

然後在現在這個情況下,你可以看到:

它已經能出來了。

當然這時候還有別的問題,就是我這個 this.a += 6 不好使。

 

這個我相信大家心裏都有譜,我們得看看,this 到底是誰:

你會發現這個 this 它是個 window,這肯定不行的。

我希望這個 this 就是我們當前的實例,也就是 damu。

所以,我這個 this,是不是就是 proxy 啊。

或者說,我這個 this,是不是就是 this._data:

所以,我們就給它指定下 this:

那麼現在有了這個之後,我們再試一次:

現在就可以看到,a 已經加了。

當然這裏面還有很多需要去適應的事,但是至少到目前爲止,還是可以出來的。

 

所以,到現在爲止,我們能夠去實現人家的核心功能,但是現在的這些東西,其實有大量值得去改進的地方。

一個最簡單的,我們現在功能是能實現,但是我們的適用面太窄了。

比方說,vue 裏面能加括號,我們這能嗎?

不能,加了括號就報錯,所以,我們是不是得判斷啊?加括號是一個版本,沒加括號又是另一個版本,很多很多的問題,都需要我們去判斷。

所以我們現在搞的這個 DOM 的編譯,僅僅只是一個很初級的版本,有太多的問題等着我們去解決。

但是我其實想讓大家明白的,是這個裏面的過程,你最重要的是理解它的思想:我們是如何把這些東西拿出來的,如何編譯的,如何替換的。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章