二、React18简介
大约 5 分钟约 1643 字
(一)Hello World
React就是用来代替DOM的
1. DOM 操作
- 通过
DOM向页面中添加一个div
// 创建一个div(DOM元素)
const div = document.createElement("div");
// 向div中设置内容
div.innerText = "我是一个div";
// 获取root
const root = document.getElementById("root");
// 将div添加到页面中
root.appendChild(div);
2. React 操作
- 通过
React向页面中添加一个div
// 创建一个div(React元素)
const div = React.createElement("div", {}, "我是React创建的div");
// 获取根元素对应的React元素
const root = ReactDOM.createRoot(document.getElementById("root"));
// 将div渲染到根元素中
root.render(div);
(二)三个 API
1. React.createElement()
- 用来创建一个
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);
});
2. ReactDOM.createRoot()
- 用来创建
React根元素 - 需要一个
DOM元素作为参数
const root = ReactDOM.createRoot(document.getElementById("root"));
3. root.render(div)
- 用来将
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
1. script标签
- 设置
JS代码被babel处理
<body>
<div id="root"></div>
</body>
<script type="text/babel"></script>
2.创建一个 React 元素: <button></button>
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作为keyindex索引会跟着元素顺序的改变而改变,所以使用索引和没有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);
};
