babel每遇到一个标签(div,span之类的html标签,或者是组件名字<App/>),就会将里面它转换成React.createElement()这个函数的调用。
image.pngReact.createElement("div", {className: "header"}, React.createElement(...))创建出来的对象,就是虚拟dom。
然后再根据虚拟dom,生成真实dom。
// 1.定义App根组件
class App extends React.Component {
constructor() {
super();
this.state = {
message: "Hello World",
};
}
render() {
const { message } = this.state;
return (
<div>
<div className="header">Header</div>
<div className="Content">
<div>{message}</div>
<ul>
<li>列表数据1</li>
<li>列表数据2</li>
<li>列表数据3</li>
<li>列表数据4</li>
<li>列表数据5</li>
</ul>
</div>
<div className="footer">Footer</div>
</div>
);
}
}
// 2.创建root并且渲染App组件
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(<App />);
"use strict";
// 1.定义App根组件
class App extends React.Component {
constructor() {
super();
this.state = {
message: "Hello World"
};
}
render() {
const { message } = this.state;
return /*#__PURE__*/ React.createElement(
"div",
null,
/*#__PURE__*/ React.createElement(
"div",
{
className: "header"
},
"Header"
),
/*#__PURE__*/ React.createElement(
"div",
{
className: "Content"
},
/*#__PURE__*/ React.createElement("div", null, message),
/*#__PURE__*/ React.createElement(
"ul",
null,
/*#__PURE__*/ React.createElement(
"li",
null,
"\u5217\u8868\u6570\u636E1"
),
/*#__PURE__*/ React.createElement(
"li",
null,
"\u5217\u8868\u6570\u636E2"
),
/*#__PURE__*/ React.createElement(
"li",
null,
"\u5217\u8868\u6570\u636E3"
),
/*#__PURE__*/ React.createElement(
"li",
null,
"\u5217\u8868\u6570\u636E4"
),
/*#__PURE__*/ React.createElement(
"li",
null,
"\u5217\u8868\u6570\u636E5"
)
)
),
/*#__PURE__*/ React.createElement(
"div",
{
className: "footer"
},
"Footer"
)
);
}
}
// 2.创建root并且渲染App组件
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(/*#__PURE__*/ React.createElement(App, null));
React.createElement(component, props, ...children)
这个children也是React.createElement()。
逗号分开。
/#PURE/
babel告诉你这个函数是纯函数调用。可以在webpack的tree-shaking里面被摇掉。不用的话,这个函数将不会被打包
jsx本质,将标签转换成Reac.createElement()函数。
Reac.createElement()函数创建出来的是ReactElement对象
虚拟dom的创建原理
image.png<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>计数器</title>
</head>
<body>
<div id="root"></div>
<script src="../lib/react.js"></script>
<script src="../lib/react-dom.js"></script>
<script>
// 1.定义App根组件
class App extends React.Component {
constructor() {
super();
this.state = {
message: "Hello World",
};
}
render() {
const { message } = this.state;
const element = React.createElement(
"div",
null,
/*#__PURE__*/ React.createElement(
"div",
{
className: "header",
},
"Header"
),
/*#__PURE__*/ React.createElement(
"div",
{
className: "Content",
},
/*#__PURE__*/ React.createElement("div", null, message),
/*#__PURE__*/ React.createElement(
"ul",
null,
/*#__PURE__*/ React.createElement(
"li",
null,
"\u5217\u8868\u6570\u636E1"
),
/*#__PURE__*/ React.createElement(
"li",
null,
"\u5217\u8868\u6570\u636E2"
),
/*#__PURE__*/ React.createElement(
"li",
null,
"\u5217\u8868\u6570\u636E3"
),
/*#__PURE__*/ React.createElement(
"li",
null,
"\u5217\u8868\u6570\u636E4"
),
/*#__PURE__*/ React.createElement(
"li",
null,
"\u5217\u8868\u6570\u636E5"
)
)
),
/*#__PURE__*/ React.createElement(
"div",
{
className: "footer",
},
"Footer"
)
);
console.log(element);
return element;
}
}
// 2.创建root并且渲染App组件
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(React.createElement(App, null));
</script>
</body>
</html>
image.png
原因是React利用ReactElement对象组成了一个JavaScript的对象树;(reactElement对象, 这个对象有props属性,里面存放着children的reatElement对象,是树结构)
JavaScript的对象树就是虚拟DOM(Virtual DOM);
虚拟dom转换成真实dom
babel将标签转换成react.createElement的函数调用。然后浏览器执行的时候,会得到react Element对象,也就是js对象。这些js对象,经过渲染,就会变成真实dom。
vue的化里面的template里面有很多指令,v-for,v-bind之类的也得解析,react中的解析更见简单明了,而且vue的template是vue自己解析的。react的jsx是babel解析的。
虚拟dom的作用(面试题)
1.没有必要重新渲染所有的真实dom。
在虚拟dom里面快速进行diff算法,来决定到底哪些东西更新,哪些东西不更新。(虚拟dom比较简单,真实的dom有很多方法之类的,很占内存空间。)
2.可以做跨平台应用程序。
虚拟dom的本质是js对象。react可以将虚拟dom渲染成真实dom。也是通过document.createElement方法渲染到web的dom上面的。ratct里面有个技术叫做react native,它可以渲染成ios,安卓上面的控件,用react开发原生的东西。
image.png
声明式编程
image.png我们最主要是在做的事情是在维护这个状态,你只需要告诉我你希望界面长什么样子,然后维护着你这里这个状态就可以了.然后呢,当状态发生改变的时候,你调这个setState,告诉我状态发生改变了,我重新渲染,那么真实的到底它的DOM如何更新,不需要你来做。
在react中是没有数据劫持的,是需要手动调用setState函数更新界面。vue中有数据劫持,当数据改变的时候,自动渲染页面。
网友评论