1.通过dom向页面添加一个div
<body>
<div id="root"></div>
<script>
/*
* React就是用来代替DOM的
* */
// 通过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>
2.通过React向页面添加一个div
// 使用函数创建react-dom对象
<body>
<div id='root'></div>
<script>
// 通过React向页面中添加一个div
/*
* React.createElement()
* - 用来创建一个React元素
* - 参数:
* 1. 元素名(组件名)
* 2. 元素中的属性
* 3. 元素的子元素(内容)
* */
// 创建元素 用核心包
// 第一个是标签名 第二个是标签上的属性 第三个是标签体
const div = React.createElement('div', {}, '我是React创建的div'); // 创建一个React元素,然后通过虚拟dom去转换
// 若此处 createElement 第三个参数是一个数组的话,需要给元素添加 key 属性
// key 属性是一个唯一值 不重复即可
// React.createElement('span', {key: '2'}, 'hello world')
// react元素要和react元素一起,不能和dom对象一起,要进行转换
// 错误 let root=document.getElementById('root')
// 用reactdom包来获取根元素对应的react元素
// 获取根元素对应的React元素
//ReactDOM.createRoot() 用来创建React根元素,需要一个DOM元素作为参数
const root = ReactDOM.createRoot(document.getElementById('root'));
// 将div渲染到根元素中
root.render(div);
</script>
</body>
3.三个API
<body>
<button id="btn">我是按钮</button>
<div id="root"></div>
<script>
/*
* React.createElement()
* - 用来创建一个React元素
* - 参数:
* 1.元素的名称(html标签必须小写),大写当组件处理,dom里document.时是可以大写的
* 2.标签中的属性
* - class属性需要使用className来设置
* - 在设置事件时,属性名需要修改为驼峰命名法
* 3.元素的内容(子元素)
* - 注意点:
* React元素最终会通过虚拟DOM转换为真实的DOM元素(native是转换为原生)
* React元素一旦创建就无法修改,只能通过新创建的元素进行替换
*
*
* */
// 创建一个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);
// 获取按钮对象
const btn = document.getElementById('btn');
btn.addEventListener('click', ()=>{
// 点击按钮后,修改div中button的文字为click me
const button = React.createElement('button', {
type: 'button',
className: 'hello',
onClick: () => {
alert('你点我干嘛')
}
}, 'click me');
// 创建一个div
const div = React.createElement('div', {}, '我是一个div', button);
// 修改React元素后,必须重新对根元素进行渲染
// 当调用render渲染页面时,React会自动比较两次渲染的元素,只在真实DOM中更新发生变化的部分
// 没发生变化的保持不变
root.render(div);
// 将元素在根元素中显示
/*
* root.render()
* - 用来将React元素渲染到根元素(空标签)中
* - 根元素中所有的内容都会被删除,被React元素所替换
* - 当重复调用render()时,React会将两次的渲染结果进行比较,
* 它会确保只修改那些发生变化的元素,对DOM做最少的修改(不会动根节点,只会动它里面的子元素不同的地方)
*
* */
});
</script>
</body>
4.两种方式
使用JSX创建React对象
两种方式:
JSX
JSX就是React.createElement()的语法糖(等价)
JSX在执行之前都会被babel转换为js代码
//第一种:
// 创建一个React元素 <button>我是按钮</button>
// 命令式编程(告诉他一步一步去怎么买水)
// const button = React.createElement('button', {}, '我是按钮');
//第二种:
// 声明式编程,结果导向的编程((直接要孩子去买水,怎么买水不管)
// 在React中可以通过JSX(JS扩展)来创建React元素,JSX需要被翻译为JS代码,才能被React执行
// 要在React中使用JSX,必须引入babel来完成“翻译”工作
// const button = <button>我是按钮</button>; // React.createElement('button', {}, '我是按钮');
五.基本脚手架
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>JSX</title>
<!-- react核心库 -->
<script src="script/react.development.js"></script>
<!-- -->
<script src="script/react-dom.development.js"></script>
<!-- 引入babel 翻译jsx成js-->
<script src="script/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<!--设置js代码被babel处理-->
<script type="text/babel">
// jsx 使用 圆括号 声明多行的 react-dom 对象
const div = (<div>
我是一个div
<button>我是按钮</button>
</div>)
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(div);
</script>
</body>
</html>
六.JSX的注意事项
<!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>
<script type="text/babel">
/*
* JSX的注意事项
* 1. JSX不是字符串,不要加引号
* 2. JSX中html标签应该小写,React组件应该大写开头
* 3. JSX中有且只有一个根标签(最外层只能有一个div)
* 4. JSX的标签必须正确结束(自结束标签必须写/)
* <input/>
* 5. 在JSX中可以使用{}嵌入表达式
* - 有值的语句的就是表达式
* 6. 如果表达式是空值、布尔值、undefined,将不会显示
* 7. 在JSX中,属性可以直接在标签中设置
* 注意:
* 在设置事件时,属性名需要修改为驼峰命名法
* class需要使用className代替
* style中必须使用对象设置
* style={{background:'red'}}
// 定义样式对象
* let myStyle = {
* width: '100px',
* height: '100px',
* backgroundColor: '#f00'
* }
* <div style={myStyle}></div>
*
* */
{/*style必须使用对象{}*/}
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/>shi
{1 + 1} <br/>
{fn()} <br/>
{/* 如果表达式是空值、布尔值、undefined,将不会显示*/}
{NaN} <br/>
{/*{if(){...}}这里就是个语句但没有值*/}
</div>
</div>;
// alert(div);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(div);
</script>
</body>
</html>
7.渲染列表
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>渲染列表</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>
<script type="text/babel">
const name = '孙悟空';
const lang = 'cn';
/*
* {} 只能用来放js表达式,而不能放语句(if for)
* 在语句中是可以去操作JSX
* */
// const div = <div>Hello {name}</div>;
let div;
if(lang === 'en'){
div = <div>hello {name}</div>;
}else if(lang === 'cn'){
div = <div>你好 {name}</div>;
}
const data = ['孙悟空', '猪八戒', '沙和尚'];
/*
<ul>
<li>孙悟空</li>
<li>猪八戒</li>
...
</ul>
// 新数组
[<li>孙悟空</li>, <li>猪八戒</li>, <li>沙和尚</li>]
* */
// 第一种。
// 为了保留原数组创建一个新数组
// const arr = [];
// 遍历data
// for(let i=0; i<data.length; i++){
// arr.push(<li>{data[i]}</li>);
// }
// 第二种:直接用map方法返回一个新数组
// map()
// * - 可以根据原有数组返回一个新数组
// * - 需要一个回调函数作为参数,回调函数的返回值会成为新数组中的元素
// * - 回调函数中有三个参数:
// * 第一个参数:当前元素
// * 第二个参数:当前元素的索引
// * 第三个参数:当前数组
// 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>
</html>
8.虚拟dom
// 发生变化的会变颜色,两两对比,改变的在原生dom里变
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>虚拟DOM</title>
<script src="script/react.development.js"></script>
<script src="script/react-dom.development.js"></script>
<script src="script/babel.min.js"></script>
</head>
<body>
<button id="btn">点我一下</button>
<hr>
<div id="root"></div>
<script type="text/babel">
//创建一个数据
const data = ['孙悟空', '猪八戒', '沙和尚'];
// 创建列表
const list = <ul>
{/*data.map(item => <li key={item}>{item}</li>)*/}
{/*map最后返回的数组*/}
{data.map((item, index) => <li key={index}>{item}</li>)}
</ul>;
// 获取根元素
const root = ReactDOM.createRoot(document.getElementById('root'));
// 渲染元素
root.render(list);
/*
* 在React我们操作的元素被称为React元素,并不是真正的原生DOM元素,
* React通过虚拟DOM 将React元素 和 原生DOM,进行映射,虽然操作的React元素,但是这些操作最终都会在真实DOM中体现出来
* 虚拟DOM的好处:
* 1.降低API复杂度
* 2.解决兼容问题
* 3.提升性能(减少DOM的不必要操作)
*
* 每当我们调用root.render()时,页面就会发生重新渲染
* React会通过diffing算法,将新的元素和旧的元素进行比较
* 通过比较找到发生变化的元素,并且只对变化的元素进行修改,没有发生的变化不予处理
* */
document.getElementById('btn').onclick = function (){
// 重新渲染页面
//创建一个数据
const data = ['唐僧', '孙悟空', '猪八戒', '沙和尚'];
// 创建列表
const list = <ul>
{/*data.map(item => <li key={item}>{item}</li>)*/}
{data.map((item, index) => <li key={index}>{item}</li>)}
</ul>;
// 渲染元素
root.render(list);
/*
* 旧数据
* ul
* li>孙悟空
* li>猪八戒
* li>沙和尚
* 新数据
* ul
* li>孙悟空
* li>猪八戒
* li>沙和尚
* 比较两次数据时,React会先比较父元素,父元素如果不同,直接所有元素全部替换
* 父元素一致,在去逐个比较子元素,直到找到所有发生变化的元素为止
* 上例中,新旧两组数据完全一致,所以没有任何DOM对象被修改
*
*
* 旧数据
* ul
* li>孙悟空
* li>猪八戒
* li>沙和尚
* 新数据
* ul
* li>tom
* li>猪八戒
* li>沙和尚
*
* 上例中,只有第一个li发生变化,所以只有第一个li被修改,其他元素不变
*
* 当我们在JSX中显示数组中,数组中每一个元素都需要设置一个唯一key,否则控制台会显示红色警告
* 重新渲染页面时,React会按照顺序依次比较对应的元素,当渲染一个列表时如果不指定key,同样也会按照顺序进行比较,
* 如果列表的顺序永远不会发生变化,这么做当然没有问题,但是如果列表的顺序会发生变化,这可能会导致性能问题出现
*
*
* 旧数据
* ul
* li>孙悟空
* li>猪八戒
* li>沙和尚
* 新数据
* ul
* li>孙悟空
* li>猪八戒
* li>沙和尚
* li>唐僧
*
* 上例中,在列表的最后添加了一个新元素,并没有改变其他的元素的顺序,所以这种操作不会带来性能问题
*
*
*
* 旧数据
* ul
* li>孙悟空
* li>猪八戒
* li>沙和尚
* 新数据
* ul
* li>唐僧
* li>孙悟空
* li>猪八戒
* li>沙和尚
*
* 上例中,在列表的最前边插入了一个新元素,其他元素内容并没有发生变化,
* 但是由于新元素插入到了开始位置,其余元素的位置全都发生变化,而React默认是根据位置比较元素
* 所以 此时,所有元素都会被修改
*
* 为了解决这个问题,React为列表设计了一个key属性,
* key的作用相当于ID,只是无法在页面中查看,当设置key以后,再比较元素时,
* 就会比较相同key的元素,而不是按照顺序进行比较
* 在渲染一个列表时,通常会给列表项设置一个唯一的key!!!!!!!!!!来避免上述问题
* (这个key在当前列表中唯一即可)
* 注意:
* 1.开发中一般会采用数据的id作为key
* 2.尽量不要使用元素的index作为key
* 索引会跟着元素顺序的改变而改变,所以使用索引做key跟没有key是一样的
* 唯一的不同就是,控制台的警告没了
* 当元素的顺序不会发生变化时,用索引做key也没有什么问题
* 旧数据
* ul
* li(key=孙悟空)>孙悟空
* li(key=猪八戒)>猪八戒
* li(key=沙和尚)>沙和尚
* 新数据
* ul
* li(key=唐僧)>唐僧
* li(key=孙悟空)>孙悟空
* li(key=猪八戒)>猪八戒
* li(key=沙和尚)>沙和尚
* */
};
</script>
</body>
</html>
版权声明:本文为weixin_44777648原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。