1.关于JSX底层处理机制
第一步:把我们编写的JSX语法,编译为虚拟DOM对象「virtualDOM」
虚拟DOM对象:框架自己内部构建的一套对象体系(对象的相关成员都是React内部规定的),基于这些属性描述出,我们所构建视图中的,DOM节点的相关特征!!
我们可以在babel中实验一下
左侧是输入编写的代码,右侧是babel编译过后的代码
我们把右侧编译过后的代码提炼出来看下
React.createElement(React.Fragment, null,
React.createElement("h2", {
className: "title",
style: styleObj
},
"\u54C8\u54C8\u54C8\u54C8"),
React.createElement("div", {
className: "box"
},
React.createElement("span", null, "x"),
React.createElement("span", null, "y")));
@1 基于 babel-preset-react-app 把JSX编译为 React.createElement(...) 这种格式!!
只要是元素节点,必然会基于createElement进行处理!
React.createElement(ele,props,...children)
+ ele:元素标签名「或组件」
+ props:元素的属性集合(对象)「如果没有设置过任何的属性,则此值是null」
+ children:第三个及以后的参数,都是当前元素的子节点
此时如果我们把createElement 方法执行结果打印出来看一下呢?
console.log(
React.createElement(React.Fragment, null,
React.createElement("h2", {
className: "title",
style: styleObj
},
"\u54C8\u54C8\u54C8\u54C8"),
React.createElement("div", {
className: "box"
},
React.createElement("span", null, "x"),
React.createElement("span", null, "y")));
)
可以看到打印出来的就是虚拟DOM对象,是react内部构建出来的,里面包含了各种属性
@2 再把 createElement 方法执行,创建出virtualDOM虚拟DOM对象「也有称之为:JSX元素、JSX对象、ReactChild对象...」!!
virtualDOM = {
$$typeof: Symbol(react.element),
ref: null,
key: null,
type: 标签名「或组件」,
// 存储了元素的相关属性 && 子节点信息
props: {
元素的相关属性,
children:子节点信息「没有子节点则没有这个属性、属性值可能是一个值、也可能是一个数组」
}
}
第二步:把构建的virtualDOM渲染为真实DOM
真实DOM:浏览器页面中,最后渲染出来,让用户看见的DOM元素!!
基于ReactDOM中的render方法处理的!!
v16
ReactDOM.render(
<>...</>,
document.getElementById('root')
);
v18
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<>...</>
);
假如要我们自己来封装一下呢?
/* createElement:创建虚拟DOM对象 */
export function createElement(ele, props, ...children) {
let virtualDOM = {
$$typeof: Symbol('react.element'),
key: null,
ref: null,
type: null,
props: {}
};
let len = children.length;
virtualDOM.type = ele;
if (props !== null) {
virtualDOM.props = {
...props
};
}
if (len === 1) virtualDOM.props.children = children[0];
if (len > 1) virtualDOM.props.children = children;
return virtualDOM;
};
补充说明:第一次渲染页面是直接从virtualDOM->真实DOM;但是后期视图更新的时候,需要经过一个DOM-DIFF的对比,计算出补丁包PATCH(两次视图差异的部分),把PATCH补丁包进行渲染!!
react中是通过胡子语法来渲染的,但是确不能直接在{}中填写对象,只有一下三种是可以直接渲染的
1.数组是可以直接渲染的;
2.标签中的style是可以在{}中直接填写对象名称的;
3.