思考:
- 浏览器是如何识别JSX的?
- 为何没有使用React时,也需要在文件顶部 import React from 'react';
一、什么是JSX?
JSX是JavaScript语法的扩展,它允许你在JS代码中,写HTML的代码片段!
// JSX语法
const app = (
<div id='app'>
Hello, chris!
</div>
);
要想让这段代码能够正确运行,需要借助工具:babel
// 第一种(借助babel让浏览器识别JSX)
<html>
<body>
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
<script type="text/babel">
const app = (
<div id='app'>
Hello, chris!
</div>
);
console.log(app);
</script>
</body>
</html>
打印出来的结果:
二、神器:babel.js
打开: ./fixtures/packaging/babel-standalone/dev.html 文件:
<div id="container"></div> <!-- 在浏览器上运行后,会显示“Hello, chris!” -->
<script type="text/babel">
ReactDOM.render(
<div id='app'>Hello, chris!</div>,
document.getElementById('container')
);
</script>
这里,有几个重点:
- div标签块;
- babel代码块;
- ReactDOM.reander方法
先来看看第3点:
/**
* @param: React.Element 不可null
* @param: DOMContainer 不可null
* @param: Function 可以null
*/
render(element: React$Element<any>,container: DOMContainer,callback: ?Function) {
invariant(
isValidContainer(container),
'Target container is not a DOM element.',
);
return legacyRenderSubtreeIntoContainer(
null,
element,
container,
false,
callback,
);
}
第一个参数类型是React.Element,第二个参数类型是DOMContainer,可是在html中:
- 第一个参数是:<div id='app'>Hello, chris!</div>
- 第二个参数是:document.getElementById('container')
这就是babel的功劳(具体可以看Babel / babel-standalone.js 源码分析):
- 浏览器发现是text/babel块,调用babel.transform,转成JSX语法;
- 默认调用React.createElement方法;
这里就回答了开关第二个问题,没有直接使用React,当有JSX语法时,也需要import react;
我们也可以不用babel块,手动创建,方式如下:
<div id="container"></div> <!-- 在浏览器上运行后,会显示“Hello, chris!” -->
<script type="text/javascript">
const element = React.createElement('div',{id:'app'},'Hello, chris!');
ReactDOM.render(
element,
document.getElementById('container')
);
</script>
三、工程/项目化
可能有同学想说,我实际开发build出来的最终文件并不是这样!
如果大家用Facebook提供的npm脚手架工具:create-react-app来生成项目,则稍微和上面讲的有所不同:那是因为,项目基于npm工程,在package.json中,引入了babel、react、webpack等相关插件,打包时,在编译阶段,webpack通过babel-loader,将JSX语法已经转成JS语法文件,因此,无需浏览器在执行阶段由JS引擎再去动态调用babel去转换JSX为JS。
<html>
<body>
<script src="../../../build/node_modules/react/umd/react.development.js"></script>
<script src="../../../build/node_modules/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
<div id="container"></div> <!-- 在浏览器上运行后,会显示“Hello, chris!” -->
<!-- 1st: babel block and need implicit import babel.js -->
<script type="text/babel">
ReactDOM.render(
<div id='app'>Hello, chris!</div>,
document.getElementById('container')
);
</script>
<!-- 2nd: javascript block but use React.createElement method -->
<script type="text/javascript">
const element = React.createElement('div',{id:'app'},'Hello, chris!');
ReactDOM.render(
element,
document.getElementById('container')
);
</script>
</body>
</html>