簡介
因?yàn)槟壳肮镜募夹g(shù)棧都是 Vue
,之前有在 React-Native
的項(xiàng)目中接觸過 React
耀态,但并沒有深入的去了解過驰吓, 從現(xiàn)在開始萌踱,我就把自己當(dāng)成一個 React
小白了,決定挑戰(zhàn)一下自己蝙泼,從 0
開始入手 React
搂擦,中間會不斷的跟 Vue
進(jìn)行對比桑逝,跟緊節(jié)奏,我們一起出發(fā)吧珊皿。
知識點(diǎn)
- React 簡介
- JSX 簡介
- Babel 語法轉(zhuǎn)換
- @babel/preset-react
- @vue/babel-preset-jsx
- Hello React
React 是什么远寸?
我就不解釋什么是 React
了唉韭,相信網(wǎng)上隨便一搜都是一大堆,截止目前為止 github
上的 star 人數(shù)已經(jīng) 165k
了吼句。
因?yàn)樵?React
項(xiàng)目中谁鳍,大部分使用的都是 JSX
語法,所以在正式學(xué)習(xí) React
之前,我們先來了解 JSX
語法今瀑。
JSX 簡介
它被稱為 JSX褒翰,是一個 JavaScript 的語法擴(kuò)展。建議在 React 中配合使用 JSX水孩,JSX 可以很好地描述 UI 應(yīng)該呈現(xiàn)出它應(yīng)有交互的本質(zhì)形式够委。JSX 可能會使人聯(lián)想到模板語言饶号,但它具有 JavaScript 的全部功能然眼。
比如:
const element = <h1>Hello, world!</h1>;
最后經(jīng)過工具轉(zhuǎn)換成 React
節(jié)點(diǎn)實(shí)例會變成這樣:
var a = /*#__PURE__*/React.createElement("div", null, "123123");
其實(shí)就是以上結(jié)果的一個簡寫晒骇,最初也就是 React
開發(fā)人員為了寫代碼方便定義的一種規(guī)范伦泥,大家用著用著覺得蠻不錯的,所以逐漸成為了一種規(guī)范了峦剔。
同樣是上面的代碼平道,經(jīng)過工具轉(zhuǎn)換成 Vue
節(jié)點(diǎn)實(shí)例會變成這樣:
const element = h("h1", ["Hello, world!"]);
下面我們利用 Babel
分析一下 React
跟 Vue
轉(zhuǎn)換 JSX
語法的過程。
Babel 對 JSX 轉(zhuǎn)換
Babel
是啥我就不解釋了稀余,可以看一下官網(wǎng)的簡介辟癌,或者感興趣的小伙伴可以看一下我之前些的一些文章:
我們直接上代碼測試一下患蹂。
首先我們創(chuàng)建一個 babel-jsx
目錄:
mkdir babel-jsx
然后在 babel-jsx
目錄執(zhí)行以下命令初始化 npm:
npm init -y
接著安裝 @babel/cli
與 @babel/core
npm install -D @babel/cli @babel/core
然后創(chuàng)建一個 src
目錄通熄,并在 src
目錄中創(chuàng)建一個 test1.js
文件:
mkdir src && touch ./src/test1.js
然后將以下代碼寫入到 src/test1.js
文件:
// 需要轉(zhuǎn)換的代碼
const code = `
const element = <h1>Hello, world!</h1>;
`;
const {parse} = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const t = require("@babel/types");
const generator = require("@babel/generator").default;
// 獲取語法 ast 語法樹
const ats = parse(code, {
sourceType: "module",
plugins: [
"jsx"
]
});
// 開始遍歷 ast 語法樹
traverse(ats, {
exit(path) {
// 當(dāng)判斷是 JSX 節(jié)點(diǎn)的時候
if (t.isJSXElement(path.node)) {
// 替換當(dāng)前的 JSX 節(jié)點(diǎn)
path.replaceWith(
t.callExpression(
t.identifier('h'),
[
t.stringLiteral(path.node.openingElement.name.name),
t.arrayExpression([t.stringLiteral(path.node.children[0].value)])
])
);
}
}
});
// 輸出轉(zhuǎn)換過后的 ast 語法樹
console.log(generator(ats));
這就是 babel
進(jìn)行轉(zhuǎn)換的過程了晓猛,(不懂的童鞋強(qiáng)烈推薦去看一下我之前的文章 babe從入門到精通:https://vvbug.blog.csdn.net/article/details/107092536)有這么幾個過程:
-
準(zhǔn)備需要轉(zhuǎn)換的代碼
const element = <h1>Hello, world!</h1>;
-
利用
@babel/parser
將代碼轉(zhuǎn)換成AST
語法樹// 獲取語法 ast 語法樹 const ats = parse(code, { sourceType: "module", plugins: [ "jsx" ] });
-
利用
@babel/traverse
遍歷AST
語法樹// 開始遍歷 ast 語法樹 traverse(ats, { exit(path) { .... }
-
利用
@babel/generator
將AST
語法樹轉(zhuǎn)換成代碼// 輸出轉(zhuǎn)換過后的 ast 語法樹 console.log(generator(ats));
我們可以測試一下帕涌。
在 babel-jsx
目錄下執(zhí)行以下命令運(yùn)行 src/test1.js
文件:
node ./src/test1.js
可以看到亲澡,我們成功的將一段 JSX
語法代碼轉(zhuǎn)換成了 Vue
中的一個節(jié)點(diǎn)實(shí)例了仰担。
@babel/preset-react
@babel/preset-react
是 Babel
官方提供的一個用來轉(zhuǎn)換 JSX
語法為 React
節(jié)點(diǎn)的 Babel
插件集合猜谚。
@babel/preset-react 官網(wǎng)地址:https://babeljs.io/docs/en/babel-preset-react
我們來試用一下。
首先安裝 @babel/preset-react
:
npm install -D @babel/preset-react
接著我們在 src
目錄下創(chuàng)建一個 test2.jsx
文件進(jìn)行測試搞坝,src/test2.jsx
文件內(nèi)容:
const element = <h1>Hello, world!</h1>;
最后我們在babel-jsx
目錄下執(zhí)行以下命令完成 babel
編譯:
npx babel ./src/test2.jsx --presets @babel/preset-react
可以看到搔谴,直接將我們的源代碼:
const element = <h1>Hello, world!</h1>;
轉(zhuǎn)換成了:
const element = /*#__PURE__*/React.createElement("h1", null, "Hello, world!");
其實(shí)經(jīng)過上面 babel
例子分析我們知道,@babel/preset-react
做的事情無非就是 babel
的 traverse
過程中的一些節(jié)點(diǎn)的處理桩撮。
@vue/babel-preset-jsx
@vue/babel-preset-jsx
是 Vue
官方提供的一個用來轉(zhuǎn)換 JSX
語法為 Vue
節(jié)點(diǎn)的 Babel
插件集合敦第。
@vue/babel-preset-jsx 官網(wǎng)地址:https://github.com/vuejs/babel-plugin-transform-vue-jsx
同樣,我們也來試用一下店量。
首先安裝 @vue/babel-preset-jsx
:
npm install -D @vue/babel-preset-jsx
然后我們在babel-jsx
目錄下執(zhí)行以下命令完成 babel
對 src/test2.jsx
文件的編譯:
npx babel ./src/test2.jsx --presets @vue/babel-preset-jsx
可以看到芜果,直接將我們的源代碼:
const element = <h1>Hello, world!</h1>;
轉(zhuǎn)換成了:
const element = h("h1", ["Hello, world!"]);
原理跟 @babel/preset-react
一樣。
Hello React
哈哈融师,學(xué)習(xí) React
第一天怎么能少了 "Hello React" 呢右钾?我們總得先體驗(yàn)一下吧。
ok,我們首先在 babel-jsx
目錄下創(chuàng)建一個 test.html
文件用來測試:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 導(dǎo)入 React 接口庫 -->
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<!-- 導(dǎo)入 React-Dom 接口庫 -->
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
</head>
<body>
<!-- 根節(jié)點(diǎn)舀射,用來掛載 React 根節(jié)點(diǎn) -->
<div id="root"></div>
<!-- 引入 babel 編譯過后的入口文件 -->
<script src="./dist/test3.js"></script>
</body>
</html>
然后我們在 src
目錄下創(chuàng)建一個 test3.jsx
文件:
ReactDOM.render(
<h1>Hello React!</h1>,
document.getElementById('root')
);
很簡單窘茁,我們用 JSX
語法創(chuàng)建了一個 "h1" 節(jié)點(diǎn),然后把這個節(jié)點(diǎn)當(dāng)成 React
的根節(jié)點(diǎn)掛載到了 root
節(jié)點(diǎn)上脆烟。
接下來我們執(zhí)行 babel
編譯命令:
npx babel ./src/test3.jsx -o ./dist/test3.js --presets @babel/react
編譯成功后山林,我們點(diǎn)開 dist/test3.js
文件:
ReactDOM.render( /*#__PURE__*/React.createElement("h1", null, "Hello React!"), document.getElementById('root'));
可以看到,babel
將我們的 JSX
語法內(nèi)容轉(zhuǎn)換成了 js
語法內(nèi)容浩淘。
最后我們在瀏覽器打開 test.html
文件看效果:
總結(jié)
我們認(rèn)識了什么是 JSX
捌朴,并且用 babel
分析了 JSX
語法的編譯過程,最后利用 CDN
+ Babel
完成了 "Hello React" 的輸出张抄,這一節(jié)還是比較輕松的砂蔽,后面馬上我們就會進(jìn)入到 React
的 api
的分析,我們將結(jié)合 Demo
深入到 React
的源碼署惯,一起加油吧左驾!