简介
因为目前公司的技术栈都是 Vue
,之前有在 React-Native
的项目中接触过 React
,但并没有深入的去了解过, 从现在开始,我就把自己当成一个 React
小白了,决定挑战一下自己,从 0
开始入手 React
,中间会不断的跟 Vue
进行对比,跟紧节奏,我们一起出发吧。
知识点
- React 简介
- JSX 简介
- Babel 语法转换
- @babel/preset-react
- @vue/babel-preset-jsx
- Hello React
React 是什么?
我就不解释什么是 React
了,相信网上随便一搜都是一大堆,截止目前为止 github
上的 star 人数已经 165k
了。
因为在 React
项目中,大部分使用的都是 JSX
语法,所以在正式学习 React
之前,我们先来了解 JSX
语法。
JSX 简介
它被称为 JSX,是一个 JavaScript 的语法扩展。建议在 React 中配合使用 JSX,JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。JSX 可能会使人联想到模板语言,但它具有 JavaScript 的全部功能。
比如:
const element = <h1>Hello, world!</h1>;
最后经过工具转换成 React
节点实例会变成这样:
var a = /*#__PURE__*/React.createElement("div", null, "123123");
其实就是以上结果的一个简写,最初也就是 React
开发人员为了写代码方便定义的一种规范,大家用着用着觉得蛮不错的,所以逐渐成为了一种规范了。
同样是上面的代码,经过工具转换成 Vue
节点实例会变成这样:
const element = h("h1", ["Hello, world!"]);
下面我们利用 Babel
分析一下 React
跟 Vue
转换 JSX
语法的过程。
Babel 对 JSX 转换
Babel
是啥我就不解释了,可以看一下官网的简介,或者感兴趣的小伙伴可以看一下我之前些的一些文章:
我们直接上代码测试一下。
首先我们创建一个 babel-jsx
目录:
mkdir babel-jsx
然后在 babel-jsx
目录执行以下命令初始化 npm:
npm init -y
接着安装 @babel/cli
与 @babel/core
npm install -D @babel/cli @babel/core
然后创建一个 src
目录,并在 src
目录中创建一个 test1.js
文件:
mkdir src && touch ./src/test1.js
然后将以下代码写入到 src/test1.js
文件:
// 需要转换的代码
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) {
// 当判断是 JSX 节点的时候
if (t.isJSXElement(path.node)) {
// 替换当前的 JSX 节点
path.replaceWith(
t.callExpression(
t.identifier('h'),
[
t.stringLiteral(path.node.openingElement.name.name),
t.arrayExpression([t.stringLiteral(path.node.children[0].value)])
])
);
}
}
});
// 输出转换过后的 ast 语法树
console.log(generator(ats));
这就是 babel
进行转换的过程了,(不懂的童鞋强烈推荐去看一下我之前的文章 babe从入门到精通:https://vvbug.blog.csdn.net/article/details/107092536)有这么几个过程:
-
准备需要转换的代码
const element = <h1>Hello, world!</h1>;
-
利用
@babel/parser
将代码转换成AST
语法树// 获取语法 ast 语法树 const ats = parse(code, { sourceType: "module", plugins: [ "jsx" ] });
-
利用
@babel/traverse
遍历AST
语法树// 开始遍历 ast 语法树 traverse(ats, { exit(path) { .... }
-
利用
@babel/generator
将AST
语法树转换成代码// 输出转换过后的 ast 语法树 console.log(generator(ats));
我们可以测试一下。
在 babel-jsx
目录下执行以下命令运行 src/test1.js
文件:
node ./src/test1.js
可以看到,我们成功的将一段 JSX
语法代码转换成了 Vue
中的一个节点实例了。
@babel/preset-react
@babel/preset-react
是 Babel
官方提供的一个用来转换 JSX
语法为 React
节点的 Babel
插件集合。
@babel/preset-react 官网地址:https://babeljs.io/docs/en/babel-preset-react
我们来试用一下。
首先安装 @babel/preset-react
:
npm install -D @babel/preset-react
接着我们在 src
目录下创建一个 test2.jsx
文件进行测试,src/test2.jsx
文件内容:
const element = <h1>Hello, world!</h1>;
最后我们在babel-jsx
目录下执行以下命令完成 babel
编译:
npx babel ./src/test2.jsx --presets @babel/preset-react
可以看到,直接将我们的源代码:
const element = <h1>Hello, world!</h1>;
转换成了:
const element = /*#__PURE__*/React.createElement("h1", null, "Hello, world!");
其实经过上面 babel
例子分析我们知道,@babel/preset-react
做的事情无非就是 babel
的 traverse
过程中的一些节点的处理。
@vue/babel-preset-jsx
@vue/babel-preset-jsx
是 Vue
官方提供的一个用来转换 JSX
语法为 Vue
节点的 Babel
插件集合。
@vue/babel-preset-jsx 官网地址:https://github.com/vuejs/babel-plugin-transform-vue-jsx
同样,我们也来试用一下。
首先安装 @vue/babel-preset-jsx
:
npm install -D @vue/babel-preset-jsx
然后我们在babel-jsx
目录下执行以下命令完成 babel
对 src/test2.jsx
文件的编译:
npx babel ./src/test2.jsx --presets @vue/babel-preset-jsx
可以看到,直接将我们的源代码:
const element = <h1>Hello, world!</h1>;
转换成了:
const element = h("h1", ["Hello, world!"]);
原理跟 @babel/preset-react
一样。
Hello React
哈哈,学习 React
第一天怎么能少了 "Hello React" 呢?我们总得先体验一下吧。
ok,我们首先在 babel-jsx
目录下创建一个 test.html
文件用来测试:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 导入 React 接口库 -->
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<!-- 导入 React-Dom 接口库 -->
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
</head>
<body>
<!-- 根节点,用来挂载 React 根节点 -->
<div id="root"></div>
<!-- 引入 babel 编译过后的入口文件 -->
<script src="./dist/test3.js"></script>
</body>
</html>
然后我们在 src
目录下创建一个 test3.jsx
文件:
ReactDOM.render(
<h1>Hello React!</h1>,
document.getElementById('root')
);
很简单,我们用 JSX
语法创建了一个 "h1" 节点,然后把这个节点当成 React
的根节点挂载到了 root
节点上。
接下来我们执行 babel
编译命令:
npx babel ./src/test3.jsx -o ./dist/test3.js --presets @babel/react
编译成功后,我们点开 dist/test3.js
文件:
ReactDOM.render( /*#__PURE__*/React.createElement("h1", null, "Hello React!"), document.getElementById('root'));
可以看到,babel
将我们的 JSX
语法内容转换成了 js
语法内容。
最后我们在浏览器打开 test.html
文件看效果:
总结
我们认识了什么是 JSX
,并且用 babel
分析了 JSX
语法的编译过程,最后利用 CDN
+ Babel
完成了 "Hello React" 的输出,这一节还是比较轻松的,后面马上我们就会进入到 React
的 api
的分析,我们将结合 Demo
深入到 React
的源码,一起加油吧!