简介
因为目前公司的技术栈都是 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
了。
- github地址:https://github.com/facebook/react/
- 官方文档地址:https://reactjs.org/docs/getting-started.html
因为在 React
项目中,大部分使用的都是 JSX
语法,所以在正式学习 React
之前,我们先来了解 JSX
语法。
JSX 简介
它被称为 JSX,是一个 JavaScript 的语法扩展。建议在 React 中配合使用 JSX,JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。JSX 可能会使人联想到模板语言,但它具有 JavaScript 的全部功能。
比如:
const element = Hello, world!
;
最后经过工具转换成 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官方文档:https://babeljs.io
- babe从入门到精通:https://vvbug.blog.csdn.net/article/details/107092536
我们直接上代码测试一下。
首先我们创建一个 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 = Hello, world!
;
`;
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 =
Hello, world!
; -
利用
@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 = Hello, world!
;
最后我们在babel-jsx
目录下执行以下命令完成 babel
编译:
npx babel ./src/test2.jsx --presets @babel/preset-react
可以看到,直接将我们的源代码:
const element = Hello, world!
;
转换成了:
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 = Hello, world!
;
转换成了:
const element = h("h1", ["Hello, world!"]);
原理跟 @babel/preset-react
一样。
Hello React
哈哈,学习 React
第一天怎么能少了 "Hello React" 呢?我们总得先体验一下吧。
ok,我们首先在 babel-jsx
目录下创建一个 test.html
文件用来测试:
Title
然后我们在 src
目录下创建一个 test3.jsx
文件:
ReactDOM.render(
Hello React!
,
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
的源码,一起加油吧!