快來跟我一起學(xué) React(Day1)

簡介

因?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 分析一下 ReactVue 轉(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)有這么幾個過程:

  1. 準(zhǔn)備需要轉(zhuǎn)換的代碼

     const element = <h1>Hello, world!</h1>;
    
  2. 利用 @babel/parser 將代碼轉(zhuǎn)換成 AST 語法樹

    // 獲取語法 ast 語法樹
    const ats = parse(code, {
        sourceType: "module",
        plugins: [
            "jsx"
        ]
    });
    
  3. 利用 @babel/traverse 遍歷 AST 語法樹

    // 開始遍歷 ast 語法樹
    traverse(ats, {
        exit(path) {
          ....
        }
    
  4. 利用 @babel/generatorAST 語法樹轉(zhuǎn)換成代碼

    // 輸出轉(zhuǎn)換過后的 ast 語法樹
    console.log(generator(ats));
    

我們可以測試一下帕涌。

babel-jsx 目錄下執(zhí)行以下命令運(yùn)行 src/test1.js 文件:

 node ./src/test1.js
1-1.png

可以看到亲澡,我們成功的將一段 JSX 語法代碼轉(zhuǎn)換成了 Vue 中的一個節(jié)點(diǎn)實(shí)例了仰担。

@babel/preset-react

@babel/preset-reactBabel 官方提供的一個用來轉(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 
1-2.png

可以看到搔谴,直接將我們的源代碼:

const element = <h1>Hello, world!</h1>;

轉(zhuǎn)換成了:

const element = /*#__PURE__*/React.createElement("h1", null, "Hello, world!");

其實(shí)經(jīng)過上面 babel 例子分析我們知道,@babel/preset-react 做的事情無非就是 babeltraverse 過程中的一些節(jié)點(diǎn)的處理桩撮。

@vue/babel-preset-jsx

@vue/babel-preset-jsxVue 官方提供的一個用來轉(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í)行以下命令完成 babelsrc/test2.jsx 文件的編譯:

npx babel ./src/test2.jsx --presets @vue/babel-preset-jsx 
1-3.png

可以看到芜果,直接將我們的源代碼:

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 文件看效果:

1-4.png

總結(jié)

我們認(rèn)識了什么是 JSX 捌朴,并且用 babel 分析了 JSX 語法的編譯過程,最后利用 CDN + Babel 完成了 "Hello React" 的輸出张抄,這一節(jié)還是比較輕松的砂蔽,后面馬上我們就會進(jìn)入到 Reactapi 的分析,我們將結(jié)合 Demo 深入到 React 的源碼署惯,一起加油吧左驾!

本節(jié)課程的完整 Demo 下載

https://gitee.com/vv_bug/react-day1-1/tree/develop/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市极谊,隨后出現(xiàn)的幾起案子诡右,更是在濱河造成了極大的恐慌,老刑警劉巖轻猖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帆吻,死亡現(xiàn)場離奇詭異,居然都是意外死亡咙边,警方通過查閱死者的電腦和手機(jī)猜煮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來败许,“玉大人王带,你說我怎么就攤上這事∈幸螅” “怎么了愕撰?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長醋寝。 經(jīng)常有香客問我搞挣,道長,這世上最難降的妖魔是什么音羞? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任柿究,我火速辦了婚禮,結(jié)果婚禮上黄选,老公的妹妹穿的比我還像新娘蝇摸。我一直安慰自己婶肩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布貌夕。 她就那樣靜靜地躺著律歼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪啡专。 梳的紋絲不亂的頭發(fā)上险毁,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機(jī)與錄音们童,去河邊找鬼畔况。 笑死,一個胖子當(dāng)著我的面吹牛慧库,可吹牛的內(nèi)容都是我干的跷跪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼齐板,長吁一口氣:“原來是場噩夢啊……” “哼吵瞻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起甘磨,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤橡羞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后济舆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卿泽,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年滋觉,在試婚紗的時候發(fā)現(xiàn)自己被綠了签夭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡椎瘟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出侄旬,到底是詐尸還是另有隱情肺蔚,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布儡羔,位于F島的核電站宣羊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏汰蜘。R本人自食惡果不足惜仇冯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望族操。 院中可真熱鬧苛坚,春花似錦比被、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至娇昙,卻和暖如春尺迂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背冒掌。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工噪裕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人股毫。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓膳音,卻偏偏與公主長得像,于是被迫代替她去往敵國和親皇拣。 傳聞我的和親對象是個殘疾皇子严蓖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容