二、React18简介
大约 5 分钟约 1643 字
(一)Hello World
React
就是用来代替DOM
的
DOM
操作
1. - 通过
DOM
向页面中添加一个div
// 创建一个div(DOM元素)
const div = document.createElement("div");
// 向div中设置内容
div.innerText = "我是一个div";
// 获取root
const root = document.getElementById("root");
// 将div添加到页面中
root.appendChild(div);
React
操作
2. - 通过
React
向页面中添加一个div
// 创建一个div(React元素)
const div = React.createElement("div", {}, "我是React创建的div");
// 获取根元素对应的React元素
const root = ReactDOM.createRoot(document.getElementById("root"));
// 将div渲染到根元素中
root.render(div);
(二)三个 API
React.createElement()
1. - 用来创建一个
React
元素
1)参数
- 元素名(组件名)
HTML
标签名,必须小写
- 标签中的属性(
id
等)class
属性需要使用className
来设置- 设置事件时,属性名需要修改为驼峰命名法,如
onClick
- 元素的子元素(内容)
2)React 元素
React
元素最终会通过虚拟DOM
转换为真实DOM
元素React
元素一旦创建就无法修改,只能通过新创建的元素进行替换
const button = React.createElement(
"button",
{
id: "btn",
type: "button",
className: "hello",
onClick: () => {
alert("你点我干嘛!");
},
},
"点我一下",
);
const div = React.createElement("div", {}, "我是一个div", button);
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(div);
// 修改已存在的React元素
// 获取按钮对象
const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
// 点击按钮后修改div中button的文字为click me
const button = React.createElement(
"button",
{
id: "btn",
type: "button",
className: "hello",
onClick: () => {
alert("你点我干嘛!");
},
},
"click me",
);
const div = React.createElement("div", {}, "我是一个div", button);
// 修改React元素后,必须重新对根元素进行渲染
// 当调用render渲染页面时,React会自动比较两次渲染的元素,只在真实DOM中更新发生变化的部分,没变化的保持不变
root.render(div);
});
ReactDOM.createRoot()
2. - 用来创建
React
根元素 - 需要一个
DOM
元素作为参数
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(div)
3. - 用来将
React
元素渲染到根元素中 - 根元素中所有的内容都会被删除,被
React
元素所替换 - 当重复调用
render
时,React
会将两次的渲染结果进行比较,会确保只修改那些发生变化的部分,对DOM
做最少的修改DOM Diffing
算法【差分算法】
// 老版本
// ReactDOM.render(div, document.getElementById('root'));
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(div);
(三)JSX
JSX
,JS 扩展,JavaScript Syntax Extension
script
标签
1. - 设置
JS
代码被babel
处理
<body>
<div id="root"></div>
</body>
<script type="text/babel"></script>
React
元素: <button></button>
2.创建一个 1)命令式编程
const button = React.createElement("button", {}, "我是按钮");
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(button);
2)声明式编程
- 在
React
中可以通过JSX
来创建React
元素,需要被翻译为JS
代码才能被React
执行 - 要在
React
中使用JSX
,必须引入babel
来完成“翻译”工作 JSX
就是React.createElement('button', {}, '我是按钮')
的语法糖JSX
在执行之前都会被babel
转换为JS
代码
const div = (
<div>
我是一个div
<button>我是按钮</button>
</div>
);
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(button);
3.注意事项
JSX
不是字符串,不要加引号JSX
中html
标签应该小写,React
组件应该大写开头JSX
中有且只有一个根标签JSX
的标签必须正确结束(自结束标签必须写/
)- 在
JSX
中可以使用{}
来嵌入表达式- 有值的语句就是表达式
- 如果表达式是空值、布尔值、
undefined
等,都不会显示在页面上 - 在
JSX
中,属性可以直接在标签中设置class
需要使用className
代替style
必须使用对象设置- 事件需要使用 半驼峰命名
const name = "aaa";
const fn = () => {
return "hello";
};
const div = (
<div>
我是一个div
<ul>
<li>列表项</li>
<li>列表项</li>
</ul>
<input type="text" />
<div
id="box"
onClick={() => {
alert("哈哈哈");
}}
className="box"
style={{ backgroundColor: "lightblue" }}
>
{name}
<br />
{1 + 1}
<br />
{fn()}
<br />
{/* {if(true){...}}<br/> */}
{null}
<br />
</div>
</div>
);
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(div);
4.渲染列表
{}
中只能放JS
表达式,不能放JS
语句(if
、for
)- 在
JS
语句中可以操作JSX
// const name = 'aaa';
// const div = (
// <div>
// Hello, {name}
// </div>
// );
const name = "bbb";
const lang = "en";
let div;
if (lang === "en") {
div = <div>Hello, {name}</div>;
} else if (lang === "cn") {
div = <div>你好, {name}</div>;
}
JSX
中会自动将数组中的元素在页面中显示
const arr = ["a", "b", "c"];
// const list = <div>{arr}</div>
const list = (
<ul>
{arr.map((item) => (
<li>{item}</li>
))}
</ul>
);
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(list);
(四)虚拟 DOM
- 在
React
中操作的元素被称为React
元素,并不是真正的原生DOM
元素 React
通过虚拟DOM
,将React
元素和原生DOM
进行映射- 虽然操作的是
React
元素,但是这些操作最终都会在真实DOM
中体现
1.虚拟 DOM 的好处
- 降低 API 复杂度
- 解决兼容性问题
- 提升性能(减少
DOM
的不必要操作)
2.注意点
- 每当调用
root.render()
时,页面就会重新渲染React
会通过Diffing
算法,将新元素和旧元素进行比较- 找到发生变化的元素,并且只对变化的元素进行修改,没变化的元素保持不变
- 比较两次数据时,
React
会先比较父元素- 父元素如果不同,直接替换所有元素
- 父元素一致,再逐个比较子元素,直到找到所有发生变化的元素为止
- 当我们在
JSX
中显示数组时,数组中每一个元素都需要设置一个唯一key
- 重新渲染页面时,
React
会按照顺序依次比较对应的元素,当渲染一个列表时如果不指定key
,同样会按照顺序进行比较 - 如果列表的顺序永远不会发生变化,没有
key
不会引发其他问题 - 如果列表的顺序发生变化,可能会导致性能问题,列表项中有表单项时页面渲染会有错误
key
的作用相当于ID
,但是不在页面中显示,React
会根据key
顺序比较新旧元素,未指定key
时按顺序比较
- 重新渲染页面时,
- 开发中一般使用
id
作为key
值 - 尽量不要使用元素的
index
作为key
index
索引会跟着元素顺序的改变而改变,所以使用索引和没有key
是一样的- 当列表顺序不变时,用索引没有问题
const arr = ["a", "b", "c"];
const list = (
<ul>
{arr.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(list);
document.getElementById("btn").onclick = function () {
const arr = ["a", "b", "c"];
const list = (
<ul>
{arr.map((item) => (
<li>{item}</li>
))}
</ul>
);
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(list);
};