v-bind和昨天提到解析內文中的{{ 表達式 }}很像,都是裡面藏著表達式,要把它換成值並觸發get做依賴收集。
const parseAttrData = (attrStr: string) => {
const attrArr = attrStr.split('=');
const key = attrArr[0].slice(1);
const value = eval(attrArr[1].slice(1, attrArr[1].length - 1));
return key + '="' + value + '"';
};
因此我們先把它從等號split開,後段扣掉第0個字和最後一個字的雙引號",用eval去執行,就是真正且完成依賴收集的屬性了。
至於普通的style如何解析,我們的目標是將標籤變成方便傳入h函數的對象,例如:
// template解析前
<div style="color:pink;border:1px solid black">雞雞</div>
// 解析後
{
tag: 'div',
props: {
style: {
color: 'pink',
border: '1px solid black'
}
},
children: ['雞雞']
}
也就是說我們要將style這樣解析:
// 解析前
'color:pink;border:1px solid black'
// 解析後
{
style: {
color: 'pink',
border: 'border:1px solid black'
}
}
需要做的事就很簡單,只需要以分號;為基準,將style字串split開,再把每一項用冒號為基準split,就能取出每一種style的key和value了。
const parseStyles = (stylesStr: string) => {
const result: Record<string, string> = {};
const styles = stylesStr.split(';');
styles.forEach(style => {
const styleArr = style.split(':');
styleArr[0] = checkSlash(styleArr[0]);
result[styleArr[0]] = styleArr[1];
});
return result;
};
// 處理style中包含'-'的屬性(ex:background-color)
const checkSlash = (styleKey: string) => {
const needUpper = styleKey.indexOf('-');
if (needUpper >= 0) return styleKey.slice(0, needUpper) + styleKey[needUpper + 1].toUpperCase() + styleKey.slice(needUpper + 2);
return styleKey;
};
最後別忘了回到parse.ts,補上import,並把我們最終解析完的textStack[0].children給return出去:
import parseAttrsString from './parseAttr';
import { parseTextData } from './parseText';
export const parse = (template: string) => {
// ......
return textStack[0].children;
}
一個簡單版的解析template就大功告成啦~
github - [Day 28]ast抽象語法樹 - 5——v-bind與style