iT邦幫忙

2023 iThome 鐵人賽

DAY 19
0
Vue.js

淺談vue3源碼,很淺的那種系列 第 29

[Day 28]ast抽象語法樹 - 5——v-bind與style

  • 分享至 

  • xImage
  •  

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


上一篇
[Day 27]ast抽象語法樹 - 4——解析屬性
下一篇
[Day 29]最後收尾!!
系列文
淺談vue3源碼,很淺的那種31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言