目录
3.1 React.createElement(元素名/组件名,元素中的元素,元素的子元素/内容)
3.2 ReactDOM.createRoot(一个DOM元素)
1. 引入React核心库和ReactDOM库
react核心库地址:https://unpkg.com/[email protected]/umd/react.development.js
react DOM库: https://unpkg.com/[email protected]/umd/react-dom.development.js
将地址在浏览器上打开下载到本地项目根目录下的script文件夹下,引入代码放在head标签内:
<!-- 引入react核心库 -->
<script src="./script/react.development.js"></script>
<!-- 引入react DOM库 -->
<script src="./script/react-dom.development.js"></script>
2. 原生DOM向页面添加新元素
<body>
<div id="root"></div>
<script>
// 通过DOM向页面中添加一个div
// 创建一个div
const div = document.createElement('div'); // 创建一个dom元素
// // 向div中设置内容
div.innerText = '我是一个div';
// // 获取root
const root = document.getElementById('root');
// // 将div添加到页面中
root.appendChild(div);
</script>
</body>
3. 通过React向页面添加新元素
<body>
<div id="root"></div>
<script>
/*
* React就是用来代替DOM的
* */
// 通过React向页面中添加一个div
/*
* React.createElement()
* - 用来创建一个React元素
* - 参数:
* 1. 元素名(组件名)
* 2. 元素中的属性
* 3. 元素的子元素(内容)
* */
// 创建一个React元素
const div = React.createElement('div', {}, '我是React创建的div');
// 获取根元素对应的React元素
// ReactDOM.createRoot() 用来创建React根元素,需要一个DOM元素作为参数
const root = ReactDOM.createRoot(document.getElementById('root'));
// 将div渲染到根元素中
root.render(div);
</script>
</body>
3.1 React.createElement(元素名/组件名,元素中的元素,元素的子元素/内容)
作用:用来创建一个React元素
参数:
1. 元素的名称(html标签必须小写)
2. 标签中的属性
- class属性需要使用className来设置
- 在设置事件时,属性名需要修改为驼峰命名法
3. 元素的内容(子元素)
注意点:
1. React元素最终会通过虚拟DOM转换为真实的DOM元素
2. React元素一旦创建就无法修改,只能通过新创建的元素进行替换
<body>
<div id="root"></div>
<script>
// 创建一个React元素
const button = React.createElement('button', {
type: 'button',
className: 'hello',
onClick: () => {
alert('你点我干嘛')
}
}, '点我一下');
// 创建第一个div
const div = React.createElement('div', {}, '我是一个div', button);
// 获取根元素
const root = ReactDOM.createRoot(document.getElementById('root'));
// 将元素在根元素中显示
root.render(div);
</script>
</body>
3.2 ReactDOM.createRoot(一个DOM元素)
作用:获取根元素 根元素就是React元素要插入的位置
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(React元素)
root.render(React元素)
作用:将元素在根元素中显示
- 用来将React元素渲染到根元素中
- 根元素中所有的内容都会被删除,被React元素所替换
- 当重复调用render()时,React会将两次的渲染结果进行比较,它会确保只修改那些发生变化的元素,对DOM做最少的修改
// 老版本的React中使用方法
ReactDOM.render(div, document.getElementById('root'));
4. JSX
声明式编程,结果导向的编程
在React中可以通过JSX(JS扩展)来创建React元素,JSX需要被翻译为JS代码(babel完成“翻译”工作),才能被React执行。
babel库地址:https://unpkg.com/[email protected]/babel.min.js
const button = <button>我是按钮</button>;
// 等价于 React.createElement('button', {}, '我是按钮');
其实JSX就是React.createElement()的语法糖,JSX在执行之前都会被babel转换为js代码。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>JSX</title>
<script src="script/react.development.js"></script>
<script src="script/react-dom.development.js"></script>
<!-- 引入babel -->
<script src="script/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<!--设置js代码被babel处理-->
<script type="text/babel">
const div = <div>
我是一个div
<button>我是按钮</button>
</div>;
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(div);
</script>
</body>
</html>
注意事项:
1. JSX不是字符串,不要加引号
2. JSX中html标签应该小写,React组件应该大写开头
3. JSX中有且只有一个根标签
4. JSX的标签必须正确结束(自结束标签必须写/)
5. 在JSX中可以使用{}嵌入表达式(有值的语句的就是表达式)
6. 如果表达式是空值、布尔值、undefined,将不会显示
7. 在JSX中,属性可以直接在标签中设置
- class需要使用className代替
- style中必须使用对象设置,style={{background:'red'}}
<body>
<div id="root"></div>
<script type="text/babel">
function fn() {
return 'hello';
}
const name = '孙悟空';
const div = <div
id="box"
onClick={() => {alert('哈哈')}}
className="box1"
style={{backgroundColor: "yellowgreen", border: '10px red solid'}}
>
我是一个div
<ul>
<li>列表项</li>
</ul>
<input type="text"/>
<div>
{name} <br/>
{1 + 1} <br/>
{fn()} <br/>
{NaN} <br/>
</div>
</div>;
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(div);
</script>
</body>
5. 判断语句
{} 只能用来放js表达式,而不能放语句(if for),在语句中是可以去操作JSX
<body>
<div id="root"></div>
<script type="text/babel">
const name = '孙悟空';
const lang = 'cn';
let div;
if (lang === 'en') {
div = <div>hello {name}</div>;
} else if (lang === 'cn') {
div = <div>你好 {name}</div>;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(div);
</script>
</body>
6. 渲染列表
原理:jsx中会自动将数组中的元素在页面中显示
将arr渲染为一个列表在网页中显示
将 ['孙悟空', '猪八戒', '沙和尚'] 变成 [<li>孙悟空</li>, <li>猪八戒</li>, <li>沙和尚</li>]
<body>
<div id="root"></div>
<script type="text/babel">
const data = ['孙悟空', '猪八戒', '沙和尚'];
// const arr = [];
// 遍历data
// for(let i=0; i<data.length; i++){
// arr.push(<li>{data[i]}</li>);
// }
// const arr = data.map(item => <li>{item}</li>);
// 将arr渲染为一个列表在网页中显示
// jsx中会自动将数组中的元素在页面中显示
// const list = <ul>{arr}</ul>;
const list = <ul>{data.map(item => <li>{item}</li>)}</ul>;
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(list);
</script>
</body>
如果新元素插入到了开始位置,其余元素的位置全都发生变化,而React默认是根据位置比较元素, 所以 此时,所有元素都会被修改。
为了解决这个问题,React为列表设计了一个key属性,key的作用相当于ID,只是无法在页面中查看,当设置key以后,再比较元素时,就会比较相同key的元素,而不是按照顺序进行比较。
// 创建列表
const list = <ul>
{/*data.map(item => <li key={item}>{item}</li>)*/}
{data.map((item, index) => <li key={index}>{item}</li>)}
</ul>;
在渲染一个列表时,通常会给列表项设置一个唯一的key来避免上述问题(这个key在当前列表中唯一即可)
注意:
1.开发中一般会采用数据的id作为key
2.尽量不要使用元素的index作为key,因为索引会跟着元素顺序的改变而改变,所以使用索引做key跟没有key是一样的 ,唯一的不同就是,控制台的警告没了。如果元素的顺序不会发生变化时,用索引做key也没有什么问题。
7. 虚拟DOM
在React我们操作的元素被称为React元素,并不是真正的原生DOM元素,
React通过虚拟DOM 将React元素 和 原生DOM,进行映射,虽然操作的React元素,但是这些操作最终都会在真实DOM中体现出来
虚拟DOM的好处:
1.降低API复杂度
2.解决兼容问题
3.提升性能(减少DOM的不必要操作)
每当我们调用root.render()时,页面就会发生重新渲染
React会通过diffing算法,将新的元素和旧的元素进行比较
通过比较找到发生变化的元素,并且只对变化的元素进行修改,没有发生的变化不予处理