一、整体的思路
- 整体上通过jsxDev函数,通过传入的参数,返回一个虚拟dom对象。
- 明确传入的参数
- 明确返回对象的属性
- 明确中间的实现步骤
- 处理key和ref属性,
- 并将其他属性添加到props对象中
二、认识JSX
1. 在官方文档里这么说的
JSX 是 JavaScript 语法扩展,可以让你在 JavaScript 文件中书写类似 HTML 的标签。虽然还有其它方式可以编写组件,但大部分 React 开发者更喜欢 JSX 的简洁性,并且在大部分代码库中使用它。
2. Javascript 本身不支持JSX
如果在普通的 JavaScript 程序中编写类似于下面的代码, 是会报错的。
javascript
const LION = <div>LION</div>
3. 让JavaScript 负责 HTML 的内容!
随着Web的交互性越来越强,逻辑越来越决定页面中的内容。这也是为什么在React中,渲染逻辑和标签共存在一个地方------组件。
4. Babel对代码做了转换
在浏览器或服务器端运行之前,JSX代码需要通过Babel等编译器转换成普通的JavaScript。这个过程中,像<div>
这样的JSX元素会被转换成React的createElement
函数调用。
jsx
let element = <div>
<div>狮子</div>
<div>LION<a style={{ color: 'blue' }} href="http://www.baidu.com">http://www.baidu.com</a></div>
</div>
javascript
let element = React.createElement("div", null,
React.createElement("div", null, "狮子"),
React.createElement("div", null, "LION:",
React.createElement("a", { style: { color: 'blue' }, href: "https://www.baidu.com" }, "https://www.baidu.com")
)
);
三、代码实现
1. 明确输入与输出
- 传入的参数为 type, config
type是节点的类型,config是参数,maybekey是为了做意外处理
- 返回的结果:
jsx
{
$$typeof: REACT_ELEMENT_TYPE, // 虚拟dom的类型
type, // 标签类型
key, // key
ref, // ref
props // 传入参数
}
2. 创建 jsxDEV函数
jsx
// 创建一个React元素的函数,处理key和ref属性,并将其他属性添加到props对象中
export function jsxDEV(type, config, maybeKey) {
// 返回一个新的React元素
return ReactElement(type, key, ref, props);
}
3. 初始化
jsx
let propName;
const props = {};
let key = null;
let ref = null;
4. 如果maybeKey参数存在
jsx
// 如果maybeKey参数存在,将其赋值给key
if (typeof maybeKey !== 'undefined') {
key = maybeKey;
}
if (hasValidKey(config)) {
key = '' + config.key;
}
5. 如果config对象中有ref
jsx
// 如果config对象中有ref属性,将其赋值给ref
if (hasValidRef(config)) {
ref = config.ref;
}
6. 遍历config对象
jsx
// 遍历config对象,将非保留属性添加到props对象中
for (propName in config) {
if (hasOwnProperty.call(config, propName)
&& !RESERVED_PROPS.hasOwnProperty(propName)
) {
props[propName] = config[propName]
}
}
7. 创建对象
jsx
// 创建一个React元素(虚拟DOM)
function ReactElement(type, key, ref, props) {
return {
$$typeof: REACT_ELEMENT_TYPE,
type,
key,
ref,
props
}
}
8. 完整代码
jsx
// 创建一个React元素的函数,处理key和ref属性,并将其他属性添加到props对象中
export function jsxDEV(type, config, maybeKey) {
let propName;
const props = {};
let key = null;
let ref = null;
// 如果maybeKey参数存在,将其赋值给key
if (typeof maybeKey !== 'undefined') {
key = maybeKey;
}
// 检查config对象中是否有ref属性
if (config.key !== undefined) {
key = '' + config.key;
}
// 如果config对象中有ref属性,将其赋值给ref
if (hasValidRef(config)) {
ref = config.ref;
}
// 遍历config对象,将非保留属性添加到props对象中
for (propName in config) {
if (hasOwnProperty.call(config, propName)
&& !RESERVED_PROPS.hasOwnProperty(propName)
) {
props[propName] = config[propName]
}
}
// 返回一个新的React元素
return ReactElement(type, key, ref, props);
}
参考内容:
- 慕课网课程:手写 React 高质量源码,迈向高阶开发
- React中文网: react.nodejs.cn/
- React源码:github.com/facebook/re...