解析屬性還是比較複雜的,需要考慮一些特殊的情況,所以我們先看比較簡單的解析文字。
解析文字需要注意的只有一點,就是文字裡面可能會藏著表達式(例如放在template的{{ 響應式變數 }})。如果我們很老實地就把解析出的文字整段原封不動直接放入textStack棧頂的children屬性,就會出現這種窘況:
// script中
const msg = ref('nmsl')
// template解析前
<div>{{ msg }}</div>
// 解析後
{
tag: 'div',
props: {},
children: ['{{ msg }}']
}
這可不是我們想要的,我們期望看到的應該是把響應式變數的值代入模板後的模樣,也就是這樣才對:
{
tag: 'div',
props: {},
children: ['nmsl']
}
再說直接把變數名連著大括號寫進虛擬dom也不會觸發響應式變數的get,自然不會進行依賴收集,如此數據更新了也不會驅動視圖。絕對是不能直接把文字賦值children的。
至於要怎麼加工呢?我們新建/src/ast/parseText.ts並寫上以下代碼:
export const parseTextData = (text: string) => {
const checkData = /{{(.+)}}/;
if (!checkData.test(text)) return text;
const express = text.match(checkData)[1];
return eval(express);
};
eval是原生js就有的方法,可以把表達式以字串的方式傳入,eval將會執行它。
因此當你把template中雙大括號內的表達式傳入eval,就能獲取響應式變數的值並填入模板,同時觸發get。eval這個方法之所以少用,是因為它會執行傳入的腳本,包括駭客傳入的惡意腳本,因此一般網頁開發上不會用eval執行來源不可信任的代碼。
不過天底下有哪個神經病會在開發自己的專案時寫惡意腳本攻擊自己的網站呢?應該是沒有啦,大概吧。
所以parseTextData需要做的事就是解析文字中的雙大括號,並eval執行雙大括號中的表達式。
如此我們便只剩下屬性的解析了,明天我們會深入討論解析屬性時可能遇到的情況。
github - [Day 26]ast抽象語法樹 - 3——解析文字