本文首發於微信公眾號:大遷世界, 我的微信:qq449245884,我會第一時間和你分享前端行業趨勢,學習途徑等等。
更多開源作品請看 GitHub https://github.com/qq449245884/xiaozhi ,包含一線大廠面試完整考點、資料以及我的系列文章。
最近正在將一個使用單檔案元件的 Options API 的 Vue2 JavaScript 專案升級為 Vue3 typescript,並利用 Composition API 的優勢。
比如,下面這種 選項API 方式:
export default {
props: {
name: {
type: String,
required: true.
}
},
emits: ['someEvent', 'increaseBy']
};
我們將它轉成 組合API 方式:
const props = defineProps<{
name: string;
}>();
const emit = defineEmits<{
(event: 'someEvent): void;
(event: 'increaseBy', value: number): void;
}>();
從 選項API 的 emit
和 props
到 組合API 的 defineemit
和 defineProps
函式的基於型別語法的轉換並不簡單。我也很好奇 Vue 是如何處理介面的。
TypeScript 介面是隻在設計和編譯時存在的結構。它們在JavaScript執行時之前被過濾掉,那麼它們是如何影響元件的行為的呢?
我想知道是否有辦法看到Vue如何解釋傳遞給 defineEmits
和 defineProps
的通用引數。如果你注意到文件中說你不需要匯入 defineEmits
和 defineProps
函式。這是因為它們實際上是同名的JavaScript函式的宏。在進行完整的 TypeScript 傳遞之前,Vue webpack外掛使用TypeScript的 AST(抽象語法樹)來推導JavaScript版本的函式選項。
如果不是因為宏:
defineProps<{
prop1: string;
prop2: number;
}>();
就會變成:
defineProps();
這樣就會導致引數缺失的錯誤。
如果看一下Vue的 SFC(單檔案元件)編譯器原始碼,有一個叫做 compileScript 的函式。我開始嘗試用最少的引數來呼叫這個函式,這樣就不會出錯,並模擬任何不重要的必要引數。最終發現了另一個叫 parse 的函式。這給了我所需的大部分引數,只剩下要mock的元件 id
。
這裡有一個小指令碼,它接收SFC的 .vue
檔案並輸出 Vue 如何解釋 TypeScript。
import { readFile, writeFile } from "fs";
import parseArgs from "minimist";
import { parse, compileScript } from "@vue/compiler-sfc";
const { file, out } = parseArgs(process.argv.slice(2), {
string: ["file", "out"],
alias: {
file: "f",
out: "o"
}
});
const filename = file;
const mockId = "xxxxxxxx";
readFile(filename, "utf8", (err, data) => {
const { descriptor } = parse(data, {
filename
});
const { content } = compileScript(descriptor, {
inlineTemplate: true,
templateOptions: {
filename
},
id: mockId
});
if (out) {
writeFile(out, "utf8", content);
} else {
process.stdout.write(content);
}
});
事例地址:https://stackblitz.com/edit/node-fzuykn?file=index.js
例如,有如以下元件:
interface Bar {
prop1: string;
prop2: number;
}
defineProps<{
bar: Bar;
bars: Bar[];
asdf1?: boolean;
asdf2: string[];
}>();
輸出:
interface Bar {
prop1: string;
prop2: number;
}
export default /*#__PURE__*/_defineComponent({
__name: 'demo',
props: {
bar: { type: Object, required: true },
bars: { type: Array, required: true },
asdf1: { type: Boolean, required: false },
asdf2: { type: Array, required: true }
},
setup(__props: any) {
return (_ctx: any,_cache: any) => {
return (_openBlock(), _createElementBlock("div"))
}
}
正如上面所看到的,SFC編譯器採用TypeScript型別資訊,並建立了 props
物件。原始型別是一對一的。介面變成物件,而 ?
可選語法驅動 required
的屬性。
程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
作者:romaopedro 譯者:前端小智 來源:logrocket
https://unicorn-utterances.com/posts/vue-composition-inspector
交流
有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。