JSX介绍
在React17之前,React是通过jsx描述视图,通过babel-loader转译后变成React.createElement(****) 形式,该函数生成vmode来描述真实dom。将来如果状态发生变化,vdom做出相应的变化,再通过diff算法对比新老vdom 从而做出最终的dom操作。
所以在React17之前 使用了jsx都需要引入react。 因为createElement函数来自React。
import React from 'react';
在React17中JSX改版了 介绍全新的 JSX 转换 , 并在 React 的 package 中引入了两个新入口,这些入口只会被 Babel 和 TypeScript 等编译器使用。新的 JSX 转换不会将 JSX 转换为 React.createElement,而是自动从 React 的 package 中引入新的入口函数并调用。
JSX返回的结构
const vdom={
key,
ref,
type,
typeof,
props:{children,className}
}
vdom是通过props的children 形成vdom树 。
createElement 和 cloneElement
createElement 和 cloneElement 都是返回ReactElement。他们的区别是cloneElement会将props合并。接来来我们从源码中获取createElement 和 cloneElement的不同之处。
- createElement
createElement 将 config属性映射到props属性上。 处理props 的children属性。
```js
function createElement(type, config, children) {
var props = {};
var key = null;
var ref = null;
var self = null;
var source = null;
//将config的属性赋值给 props
if (config != null) {
}
//去掉 type 和config 剩余的当 children处理
var childrenLength = arguments.length - 2;
props.children = childArray;
return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
}
//处理的key和ref 就是在props上添加key和ref属性--监听get
Object.defineProperty(props, 'key', {
get: warnAboutAccessingKey,
configurable: true
});
Object.defineProperty(props, 'ref', {
get: warnAboutAccessingRef,
configurable: true
});
```
- cloneElement (一些属性值的初始值 来自element,比如 props /key /self)
function cloneElement(element, config, children) {
var props = assign({}, element.props); // Reserved names are extracted
var props = assign({}, element.props); // Reserved names are extracted
var key = element.key;
var ref = element.ref;
var self = element._self;
var source = element._source;
var owner = element._owner;
//处理 config属性 映射到 props属性上
if (config != null) {
}
//和createElement 一样
var childrenLength = arguments.length - 2;
props.children = childArray;
return ReactElement(element.type, key, ref, self, source, owner, props);
}
- ReactElement 返回element 其实就是js对象 ,这个js对象就是vdom , props通过children属性形成 树状图。
var ReactElement = function (type, key, ref, self, source, owner, props) {
var element = {
$$typeof: REACT_ELEMENT_TYPE,
type: type,
key: key,
ref: ref,
props: props,
_owner: owner
};
{
element._store = {};
Object.defineProperty(element._store, 'validated', {
configurable: false,
enumerable: false,
writable: true,
value: false
});
Object.defineProperty(element, '_self', {
configurable: false,
enumerable: false,
writable: false,
value: self
});
Object.defineProperty(element, '_source', {
configurable: false,
enumerable: false,
writable: false,
value: source
});
if (Object.freeze) {
Object.freeze(element.props);
Object.freeze(element);
}
}
return element;
};
-
elemen的type类型
- classComponent //isReactComponent 标识 类组件 React.prototype.isReactComponent={};
Component.prototype.setStateComponent.prototype.forceUpdate2. PureComponent
```js ComponentDummy.prototype = Component.prototype; var pureComponentPrototype = PureComponent.prototype = new ComponentDummy(); pureComponentPrototype.constructor = PureComponent; assign(pureComponentPrototype, Component.prototype); //isPureReactComponent 为true 标识 为PureComponent pureComponentPrototype.isPureReactComponent=true; ``` ----- * PureComponent 继承 Component * isPureReactComponent 为true 标识 为PureComponent * 进行props 和 state 浅比较 通过Object.is()进行比较 (源码 -- checkShouldComponentUpdate 函数) ```js if (ctor.prototype && ctor.prototype.isPureReactComponent) { return !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState); function shallowEqual(objA, objB) { if (objectIs(objA, objB)) { return true; } if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { return false; } var keysA = Object.keys(objA); var keysB = Object.keys(objB); if (keysA.length !== keysB.length) { return false; } for (var i = 0; i < keysA.length; i++) { if (!hasOwnProperty$2.call(objB, keysA[i]) || !objectIs(objA[keysA[i]], objB[keysA[i]])) { return false; } } return true; } ``` 3. Html 原生标签 4. 文本 5. Fragment -
createElement和cloneElement的小结:
-
createElement和cloneElement都是返回 element。就是vdom结构。
-
cloneElement其实就是对element(第一个参数)的扩展。
-