高性能、声明式、组件化、单向响应的数据流、JSX扩展、灵活
<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>01.React初体验</title>
<!--1、引入react核心文件-->
<script src="./js/react.development.js"></script>
<!--2、引入react-dom文件-->
<script src="./js/react-dom.development.js"></script>
</head>
<body>
<!--3、创建容器元素-->
<div id="root"></div>
<script>
//4、通过ReactDOM来创建挂载的根容器
const root = ReactDOM.createRoot(document.querySelector('#root'));
//5、通过root.render来指定呈现的内容
root.render('尚硅谷');
</script>
</body>
可以渲染
的内容类型(数组类型、数值类型、字符串类型)不可以渲染
的内容类型,会报错 (对象和函数不能渲染,但是函数中可以return让render能渲染的内容类型,json对象字符串可以渲染)不会报错,但不会渲染内容
的类型 //5、通过root.render来指定呈现的内容
//5.1 undefined类型
//root.render(undefined);
//5.2 空
//root.render();
//5.3 null
//root.render(null);
//5.4 true
//root.render(true);
//5.5 false
root.render(false);
语法:
*React.createElement(标签名,标签属性对象,值)*
标签属性:需要传入一个对象,设置:键值对,不设置:
空对象{}或者null
语法:
*React.createElement(标签名,标签属性,子节点1,子节点2...)*
同级标签
*React.createElement(标签名,标签属性,React.createElement(标签名,标签属性.'内容')*
子标签
包含多个元素:从第三个参数开始即是包裹的内容。或将第三个参数设置为数组,
如果第三个参数设置为数组,数组元素需要增加唯一key属性
。
//6、render可以接收虚拟DOM,会将虚拟DOM转为真实Dom
//6.1 渲染指定元素
// root.render(我是一个DIV)
一个元素包裹多个元素
如果元素是单标签,必须闭合
如果元素较多可以换行,建议这样做添加 ()
JSX中标签必须闭合,单双标签都必须
JSX有且只能是一个根元素
可以使用包裹标签:包裹标签不会被编译(不会渲染),只是起到包裹的作用。
<React.Fragment></React.Fragment>
必须使用 {} 包裹
{ // 我是注释 }
{ /* 添加多行注释*/ }
语法 {}
{指定动态的属性值和标签体文本
}中填写变量值。
不会进行渲染
。不允许是对象
不允许在{}内写JS语句
在React中实现条件渲染的方式有以下三种:
if…else
当判断的条件较多时,我们还可以采用函数的方式
三元表达式
逻辑短路
注意: 只适用于只在一种情况下才有界面的情况(也就是说当条件满足时即有界面否则没有,并非二选一)
表达式1 && 表达式2
如果表达式1对应的boolean为true, 返回表达式2的值
如果表达式1对应的boolean为false, 返回表达式1的值
表达式1 || 表达式1
如果表达式1对应的boolean为true, 返回表达式1的值
如果表达式1对应的boolean为false, 返回表达式2的值
const root = ReactDOM.createRoot(document.querySelector("#root"));
const vDom = isLogin && <h2>恭喜您,登录成功</h2>;
root.render(vDom);
作用:为属性指定数据,可以直接使用{},不需要加双引号
constimgUrl = "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png"
const w = 110;
<img src={imgUrl} width={w} />
react中可以将数组中的元素依次渲染到页面上,可以直接往数组中存储react元素,推荐使用数组的 map 方法
注意:必须给列表项添加唯一的 key 属性, 推荐使用id作为key, 尽量不要用index作为key
行内样式(style)
style属性值是一个对象,
带有"-"的属性名需要写成驼峰命名
当属性值单位为px的时候,且值为number类型,可以省略单位,直接写成数值
非行内样式(className) 尚硅谷
React 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:
React 事件的命名采用小驼峰式(camelCase)
,而不是纯小写。比如:onClick、onFocus 、onMouseEnter
使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串
const div = <div onClick={事件处理函数}></div>
React 根据 W3C 规范来自定义的合成事件, 与原生事件不完全相同
处理好了浏览器的兼容性问题
阻止事件默认行为不能使用 return false, 必须要调用: event.preventDefault()
有自己特有的属性, 比如: nativeEvent – 原生事件对象
的 change 监听在输入过程中触发, 而原生是在失去焦点才触发
原理:内部绑定的是原生 input 事件
在事件对象中属性虽然很多,但是一点要记住的有两点:
e.preventDefault()
技术栈:React基本操作+虚拟DOM+函数组件+JSX+类组件+脚手架+Hooks+ajax+路由+UI组件+redux+TS
。
React 是一个用于构建用户界面
的 JAVASCRIPT 库,所以React并不是框架,而是一个用于前端数据渲染的库
。
而人们常指的React框架指的是:react
+react-router
+react-redux
的组合。
React 主要用于构建 UI, 起源于 Facebook 的内部项目,并于 2013 年 5 月开源,本身只关注界面,。
例如:前后台交互(axios)、路由管理(Router)、状态管理(redux) 等都由其扩展插件,需要单独安装
React 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它。
英文官网: https://reactjs.org/
中文官网: https://react.zcopy.site/
高性能
:虚拟DOM(Virtual DOM)配合 diff 算法,最大限度地减少与 DOM 的交互。
声明式
:React采用声明式编码UI,可以轻松实现交互式UI,让代码更加可行且方便调试。
组件化
:通过 React 构建组件,使得代码更加容易得到复用,能够高效率的应用在大项目的开发中。
单向响应的数据流
:React 中的数据是单向自顶向下
传递的,父组件数据的更新会自动传递到子组件
但子组件的数据更新不会影响到父组件,也不能在子组件修改父组件传入的数据
JSX扩展
:JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但官网建议使用它。
灵活
:React可以与已知的库或框架很好的进行配合。
安装版本:18.2.0【最新版本】
使用步骤:
<script src="./js/react.development.js"></script>
<script src="./js/react-dom.development.js"></script>
<div id="root"></div>
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render("尚硅谷");
<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>01.React初体验</title>
<!--1、引入react核心文件-->
<script src="./js/react.development.js"></script>
<!--2、引入react-dom文件-->
<script src="./js/react-dom.development.js"></script>
</head>
<body>
<!--3、创建容器元素-->
<div id="root"></div>
<script>
//4、通过ReactDOM来创建挂载的根容器
const root = ReactDOM.createRoot(document.querySelector('#root'));
//5、通过root.render来指定呈现的内容
root.render('尚硅谷');
</script>
</body>
但是在这里,有几点注意事项需要大家注意
:
root.render('尚硅谷');
root.render('百度');
root.render('京东');
root.render('淘宝');
<div id="root"></div>
<div class="app" id="one"></div>
<script>
//4、通过ReactDOM来创建挂载的根容器
const app = ReactDOM.createRoot(document.querySelector('.app'));
const one = ReactDOM.createRoot(document.querySelector('#one'));
//5、通过root.render来指定呈现的内容
app.render("尚硅谷");
one.render('京东');
</script>
会产生一个报错:
Warning: You are calling ReactDOMClient.createRoot() on a container that has already been passed to createRoot() before. Instead, call root.render() on the existing root instead if you want to update it.
<div id="root"></div>
<div class="app" id="one"></div>
<script>
//4、通过ReactDOM来创建挂载的根容器
const app = ReactDOM.createRoot(document.querySelector('.app'));
const root = ReactDOM.createRoot(document.querySelector('#root'));
//5、通过root.render来指定呈现的内容
app.render("尚硅谷");
root.render('京东');
</script>
可以渲染
的内容类型<body>
<!--3、创建容器元素-->
<div id="root"></div>
<script>
//4、通过ReactDOM来创建挂载的根容器
const root = ReactDOM.createRoot(document.querySelector('#root'));
//5、通过root.render来指定呈现的内容
//5.1 字符串类型
//root.render("尚硅谷");
//注意:如果字符串中包含html标签,会被作为文本处理,类似于JS中的innerText
//root.render("尚硅谷");
//5.2 数值类型
//root.render(100);
//注意:虽然写入的值是数字,但是是按照字符串的方式写入
//5.3 数组类型
//注意:如果类型是数组,会被直接展开(无逗号)
root.render([1, 2, 3, 4])
</script>
</body>
不可以渲染
的内容类型 (对象和函数不能渲染)<body>
<!--3、创建容器元素-->
<div id="root"></div>
<script>
//4、通过ReactDOM来创建挂载的根容器
const root = ReactDOM.createRoot(document.querySelector('#root'));
//5、通过root.render来指定呈现的内容
//类型不允许是对象
root.render({ a: 1, b: 2 })
//但是如果是JSON对象字符串就可以了
root.render(JSON.stringify({ a: 1, b: 2 }));
</script>
</body>
报错:
Uncaught Error: Objects are not valid as a React child (found: object with keys {a, b}). If you meant to render a collection of children, use an array instead.
不会报错,但不会渲染内容
的类型<body>
<!--3、创建容器元素-->
<div id="root"></div>
<script>
//4、通过ReactDOM来创建挂载的根容器
const root = ReactDOM.createRoot(document.querySelector('#root'));
//5、通过root.render来指定呈现的内容
//5.1 undefined类型
//root.render(undefined);
//5.2 空
//root.render();
//5.3 null
//root.render(null);
//5.4 true
//root.render(true);
//5.5 false
root.render(false);
</script>
</body>
<body>
<!--3、创建容器元素-->
<div id="root"></div>
<script>
//4、通过ReactDOM来创建挂载的根容器
// const root = ReactDOM.createRoot(document.body);
const root = ReactDOM.createRoot(document.documentElement);
//5、通过root.render来指定呈现的内容
root.render('尚硅谷');
</script>
</body>
渲染到Body会报错:
Warning: createRoot(): Creating roots directly with document.body is discouraged, since its children are often manipulated by third-party scripts and browser extensions. This may lead to subtle reconciliation issues. Try using a container element created for your app.
渲染到html会报错:
Warning: validateDOMNesting(...): Text nodes cannot appear as a child of <html>.
虚拟DOM的本质是一个普通对象,虚拟DOM的属性会与真实DOM的属性一一对应,虚拟DOM是轻量级的;
真实DOM是重量级的,虚拟DOM最终都会通过React转为真实DOM进行渲染;React操作的都是虚拟DOM。
虚拟DOM元素的创建有两种方式:
浏览器向服务器发送请求(请求报文),服务器会给予浏览器响应报文,浏览器会将接收到的响应体中的内容进行
渲染,在进行渲染的过程中如果有CSS,会将CSS进行解析,往往也会加载JS,如果JS对页面结构进行操作的话有可
能产生重排重绘,那么具体什么是重排重绘
呢?
重排:
重绘:
重排之后会进行渲染,该渲染称为重绘。
例如:
this.style.width = “100px”;
this.style.height= “200px”;
而通过虚拟DOM,可以大大减少重排重绘。
语法:React.createElement(标签名,标签属性对象,值)
标签属性:需要传入一个对象,设置:键值对,不设置:空对象
{}或者null
<body>
<!--3、创建容器元素-->
<div id="root"></div>
<script>
//4、通过ReactDOM来创建挂载的根容器
const root = ReactDOM.createRoot(document.querySelector('#root'));
//React.createElement
//参数1:是虚拟DOM的名字:对应虚拟DOM对象中的type属性
const vDOM = React.createElement('h1');
//console.log(vDOM);
//{$$typeof: Symbol(react.element), type: 'h1', key: null, ref: null, props: {…}}
//参数2:类型是一个对象
//const vDOM = React.createElement("div", {}); //没有属性时 方法一:{}
//const vDOM = React.createElement("div", null);//没有属性时 方法二:null
const vDOM = React.createElement("div", { id: 'box', className: "box" });
console.log(vDOM);
//参数3:第三个参数是包裹的内容
const vDOM = React.createElement("div", { id: 'box', className: "box" }, "尚硅谷");
console.log(vDOM);
//5、render可以接收虚拟DOM,会将虚拟DOM转为真实Dom
root.render(vDOM)
</script>
</body>
注意:如果想要创建的标签中嵌套其他子标签时
语法:React.createElement(标签名,标签属性,子节点1,子节点2…)
const vDOM1 = React.createElement('a', { href: "http://www.taobao.com" }, '淘宝');
const vDOM = React.createElement("h1", { title: '尚硅谷', id: "box", className: "box" }, React.createElement('span', null, '百度'), React.createElement('p', null, vDOM1));
console.log(vDOM);
root.render(vDOM);
包含多个元素:从第三个参数开始即是包裹的内容。或将第三个参数设置为数组,
如果第三个参数设置为数组,数组元素需要增加唯一key属性
。
const vDOM1 = React.createElement('a', { href: "http://www.taobao.com", key: '1' }, '淘宝');
const vSpan = React.createElement('span', { key: '2' }, '百度');
const vDOM = React.createElement("h1", { title: '尚硅谷', id: "box", className: "box" }, [vDOM1, vSpan]);
console.log(vDOM);
root.render(vDOM);
小结:
虚拟 DOM
(virtual DOM) 或虚拟节点
(virtual Node),虚拟DOM的本质是一个对象,它不是真实 DOM 元素对象。较轻
的对象;真实 DOM: 属性特别多 ==> 较重
的对象虚拟 DOM 对象包含了对应的真实 DOM 的关键信息属性。
属性 | 示例 |
---|---|
标签名 | type: “h1” |
标签属性 | props: {title: ‘你好, React!’} |
子节点 | props: {children: ‘Hello React!’} |
问题
: React.createElement() 写起来太复杂了
解决
: 官方推荐使用更加简洁的JSX
JSX 是一种 JS 的扩展语法, 本质是React.createElement方法的语法糖,用来快速创建 React 元素(虚拟DOM/虚拟节
点),形式上像 HTML 标签/任意其它标签, 且标签内部是可以套 JS 代码的,浏览器并不认识 JSX
。
所以需要引入babel将 JSX 编译成 React.createElement 的形式线上测试: https://www.babeljs.cn/
<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>Document</title>
<!--1、引入react核心文件-->
<script src="./newjs/react.development.js"></script>
<!--2、引入react-dom文件-->
<script src="./newjs/react-dom.development.js"></script>
<!--3、引入babel转换文件-->
<script src="./js/babel.min.js"></script>
</head>
<body>
<!--4、创建容器元素-->
<div id="root"></div>
<script type="text/babel">
//5、通过ReactDOM来创建挂载的根容器
const root = ReactDOM.createRoot(document.querySelector("#root"));
//6、render可以接收虚拟DOM,会将虚拟DOM转为真实Dom
//6.1 渲染指定元素
// root.render(我是一个DIV)
//6.2 一个元素包裹多个元素
// root.render(12
);
//6.3 如果元素是单标签,必须闭合
//常见的单标签,例如:img、br、hr、input等
root.render(<div><br/></div>);
//6.4 如果元素较多可以换行,但不建议这样做:
// root.render(
//
// 1
// 2
//
// )
//6.5 如果元素较多可以换行,建议这样做:
// root.render(
// (
//
// 1
// 2
//
// )
// )
//6.6 JSX必须闭合
// root.render();// 正确
// root.render();// 正确
// root.render();// 不正确
//6.7 JSX有且只能是一个根元素,以下这种写法不允许
// root.render(
// (
// 1
// 2
// )
// )
// 以下可以解决问题,我们一般会选择可以包含所有行标签和块标签的元素来作为唯一的根元素
// root.render(
// (
//
// 1
// 2
//
// )
// )
//6.8 可以使用包裹标签:包裹标签不会被编译(不会渲染),只是起到包裹的作用。
//
// root.render(
// (
//
// 1
// 2
//
// )
// )
//对React对象进行解构赋值:首字大写的标签会被作为组件使用。
// const { Fragment } = React;
// root.render(
// (
//
// 1
// 2
//
// )
// )
//6.9 后期我们一般会将JSX结构单独定义出来,常量或者变量均可,主要为了方便后期定义组件
// const vDOM =
// 3
// 4
//
// root.render(vDOM);
</script>
</body>
2.3.2 注释
在React中,注释的写法仍然支持单行注释以及多行注释。
<body>
<!--4、创建容器元素-->
<div id="root"></div>
<script type="text/babel">
//5、通过ReactDOM来创建挂载的根容器
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render((
<div>
{
//我是单行注释
}
{
/*
* 我
* 是
* 多
* 行
* 注
* 释
*/
}
{
// 1
// 2
// 3
}
{
/*
* 1
* 2
* 3
*/
}
{/* 注释内容 */}
</div>
))
</script>
</body>
2.3.3 插值表达式
我们学习插值表达式之前,大家需要先弄懂一个概念,容易混淆,那就是表达式
和语句
之间的区别。
- 表达式:会产生一个值,可以放在任何一个需要值的地方。
例如:
(1).100
(2).a
(3).demo()
(4).x === y ? 1 : 0
(5). 200 - 2
(6). arr.map()
- 语句(代码): 不会产生值,只是控制代码走向
例如:
(1). if(){}
(2). for(){}
(3). try{} catch(err){}
(4). switch
....
在之前的工程化阶段的时候,我们学过ejs模板语法<%= xxx %>,在JSX中直接使用{}
表示即可。
作用: 指定动态的属性值和标签体文本
。
接下来我们来说一说,在插值表达式中的语法:
- 可以是任意基本类型数据值
- 如果{}内的是用双引号,单引号,反引号包裹,则是字符串;
- 如果{}内是数字,即是要输出该数字;
- 如果{}内是undefined,null,true,false
不会进行渲染
。
- 可以是一个 JS 数组,会直接进行展开渲染(不包含逗号 ),
不允许是对象
- 可以是 JS 的表达式,
不允许在{}内写JS语句
- 可以是 react 元素对象
<body>
<!--4、创建容器元素-->
<div id="root"></div>
<script type="text/babel">
//5、通过ReactDOM来创建挂载的根容器
const root = ReactDOM.createRoot(document.querySelector("#root"));
//定义字符串
const str = "尚硅谷";
//定义数值
const num = 100;
//定义函数体
function fun() {
return 'fun...'
}
//定义对象
const obj = {
a: 1,
b: 2
}
//6、render可以接收虚拟DOM,会将虚拟DOM转为真实DOM
const vDOM = <div>
<p>{str}</p>
<p>{"字符串1"}</p>
<p>{'字符串2'}</p>
<p>{`字符串3`}</p>
<p>{100}</p>
<p>{num}</p>
<p>{"字符串1" + num}</p>
<p>{true}</p>
<p>{false}</p>
<p>{undefined}</p>
<p>{1 === 1}</p>
<p>{React.createElement("span", null, '虚拟DOM')}</p>
<p>{fun()}</p>
<p>{num === 1 ? ' 男' : '女'}</p>
<p>{str.split("").reverse()}</p>
<p>{[1, 2, 3, 4]}</p>
{/*
{obj}
{{ a: 1, b: 2 }}
*/}
</div>
root.render(vDOM);
</script>
</body>
2.3.4 条件渲染
在React中实现条件渲染的方式有以下三种:
- if…else
const root = ReactDOM.createRoot(document.querySelector("#root"));
let vDom;
if (isLogin) {
vDom = <h2>恭喜您,登录成功</h2>
} else {
vDom = <div><button>登录</button><button>注册</button></div>
}
root.render(vDom);
当判断的条件较多时,我们还可以采用函数的方式
const root = ReactDOM.createRoot(document.querySelector("#root"));
//当条件判断的条件较多,我们可以采用函数来定义
function fun(score) {
if (score > 60 && score < 70) return '及格';
if (score >= 70 && score < 80) return '中';
if (score >= 80 && score < 90) return '良';
if (score >= 90 && score <= 100) return '优秀';
return '不及格';
}
//6、render可以接收虚拟DOM,会将虚拟DOM转为真实DOM
const vDOM = <div>
{fun(50)}
</div>
root.render(vDOM);
- 三元表达式
const root = ReactDOM.createRoot(document.querySelector("#root"));
const vDom = isLogin ? <h2>恭喜您,登录成功</h2> :
<div><button>登录</button><button>注册</button></div>
root.render(vDom);
-
逻辑短路
注意: 只适用于只在一种情况下才有界面的情况(也就是说当条件满足时即有界面否则没有,并非二选一)
-
表达式1 && 表达式2
如果表达式1对应的boolean为true, 返回表达式2的值
如果表达式1对应的boolean为false, 返回表达式1的值
-
表达式1 || 表达式1
如果表达式1对应的boolean为true, 返回表达式1的值
如果表达式1对应的boolean为false, 返回表达式2的值
const root = ReactDOM.createRoot(document.querySelector("#root"));
const vDom = isLogin && <h2>恭喜您,登录成功</h2>;
root.render(vDom);
2.3.5 属性渲染
作用:为属性指定数据,可以直接使用{},不需要加双引号
<body>
<!--4、创建容器元素-->
<div id="root"></div>
<script type="text/babel">
//5、通过ReactDOM来创建挂载的根容器
const root = ReactDOM.createRoot(document.querySelector("#root"));
const url = "http://www.atguigu.com";
const imgUrl = "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png"
const w = 110;
const vDOM = <div>
<a href="http://www.atguigu.com">尚硅谷</a>
<a href={url}>尚硅谷</a>
<img src={imgUrl} width={w} />
</div>
//6、渲染
root.render(vDOM);
</script>
</body>
2.3.6 列表渲染
react中可以将数组中的元素依次渲染到页面上,可以直接往数组中存储react元素,推荐使用数组的 map 方法
注意:必须给列表项添加唯一的 key 属性, 推荐使用id作为key, 尽量不要用index作为key
<body>
<!--4、创建容器元素-->
<div id="root"></div>
<script type="text/babel">
//5、通过ReactDOM来创建挂载的根容器
const root = ReactDOM.createRoot(document.querySelector("#root"));
//6.1 数组是可以被直接展开的
// let arr = [1, 2, 3, 4];
// root.render((
//
// {arr}
//
// ));
//6.2 数组中的元素也可以是JSX
// let arr = [
// 1,
// 2,
// 3,
// 4
// ]
// root.render((
//
// {arr}
// 1
// 2
// 3
// 4
//
// ));
//6.3 如果使用map,map接收的是一个箭头函数,明白{},()的区别
let arr = [1, 2, 3, 4];
//匿名函数
/* let arr1 = arr.map(function (item, index) {
// return {item}
return (
{item}
)
})
console.log(arr1);
root.render(arr1); */
//箭头函数
// let arr2 = arr.map((item, index) => {
// return (
// {item}
// )
// })
// console.log(arr2);
// root.render(arr2);
//注意:{}:如果要返回内容需要使用return,()返回的内容
const vDOM = <div>
{
arr.map((item, index) => {
return (
<span key={index}>{item}</span>
)
})
}
</div>
root.render(vDOM);
</script>
</body>
案例需求: 根据下面的数组显示列表
const courses = [ {id: 1, name: ‘React’}, {id: 3, name: ‘Vue’}, {id: 5, name: ‘小程序’} ]
<body>
<!--3、创建一个容器元素-->
<div id="root"></div>
<script type="text/babel">
const root = ReactDOM.createRoot(document.querySelector('#root'));
const courses = [{ id: 1, name: 'React' }, { id: 3, name: 'Vue' }, { id: 5, name: '小程序' }]
const vDOM = <div>
{
courses.map((item) => {
return <p key={item.id}>{item.name}</p>
})
}
</div>
root.render(vDOM)
</script>
</body>
2.3.7 样式渲染
- 行内样式(style)
<body>
<!--3、创建一个容器元素-->
<div id="root"></div>
<script type="text/babel">
const root = ReactDOM.createRoot(document.querySelector('#root'));
//style样式
//1、react中不允许将style属性设置为字符串,否则会有异常:
// root.render((
// 尚硅谷
// ));
//报错:Uncaught Error: The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + 'em'}} when using JSX.
//2、style属性值是一个对象
// root.render((
//
// width: '100px',
// height: '100px',
// background: 'red'
// }}>尚硅谷
// ));
//3、带有"-"的属性名需要写成驼峰命名
// root.render((
//
// width: '100px',
// height: '100px',
// background: 'red',
// marginLeft: '100px'
// }}>尚硅谷
// ));
//4、当属性值单位为px的时候,且值为number类型,可以省略单位,直接写成数值
root.render((
<div style={{
width: 100,
height: 100,
background: 'red',
marginLeft: 100
}}>尚硅谷</div>
));
</script>
</body>
- 非行内样式(className)
<body>
<!--3、创建一个容器元素-->
<div id="root"></div>
<script type="text/babel">
const root = ReactDOM.createRoot(document.querySelector('#root'));
const box = 'box'
//className样式
root.render((
<div>
<p className="box">尚硅谷</p>
<p className={1 > 2 ? 'box' : 'box1'}>京东</p>
</div>
))
</script>
</body>
2.3.7 关于事件
- 绑定事件
React 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:
React 事件的命名采用小驼峰式(camelCase)
,而不是纯小写。比如:onClick、onFocus 、onMouseEnter
使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串
const div = <div onClick={事件处理函数}></div>
- 事件对象
React 根据 W3C 规范来自定义的合成事件, 与原生事件不完全相同
-
处理好了浏览器的兼容性问题
-
阻止事件默认行为不能使用 return false, 必须要调用: event.preventDefault()
-
有自己特有的属性, 比如: nativeEvent – 原生事件对象
-
的 change 监听在输入过程中触发, 而原生是在失去焦点才触发
- 原理:内部绑定的是原生 input 事件
//声明一个函数
function fn1() {
console.log('fn1....')
}
let fn2 = () => {
console.log('fn2...')
}
function fn3(a, b) {
// return function () {
// console.log('fn3....')
// console.log(a, b)
// }
//还可以返回箭头函数
return () => {
console.log(a, b)
}
}
let fn4 = e => {
console.log(e);
//在事件对象中属性虽然很多,但是一点要记住的有两点:
//1、实际发生事件的目标对象(由于最终虚拟DOM要转换成真实DOM,所以e.target获取的都是真实DOM):e.target
// console.log(e.target)
// console.log(e.target.innerHTML)
//2、关于事件默认行为的取消:e.preventDefault()
}
let fn5 = e => {
//取消事件的默认行为
e.preventDefault();
alert('我是弹框');
}
let fn6 = () => {
console.log('fn6...');
}
//6、创建一个虚拟DOM
const vDOM = <div>
<button onClick={function () { console.log('我是普通函数') }}>普通函数</button>
<button onClick={() => { console.log('我是箭头函数') }}>箭头函数</button>
<hr />
<h4>事件中带入函数名</h4>
<button onClick={fn1}>普通函数</button>
<button onClick={fn2}>箭头函数</button>
<hr />
<h4>如果事件中函数调用了,适用于带参的情况</h4>
<button onClick={fn3(10, 20)}>普通函数</button>
<hr />
<button onClick={fn4}>关于事件对象的处理</button>
<a href="http://www.atguigu.com" onClick={fn5}>尚硅谷</a>
<input onChange={fn6} />
</div>
//7、渲染
const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(vDOM);
综合练习1-新闻列表
* {
margin: 0;
padding: 0;
list-style: none;
}
.hot-news {
width: 500px;
margin: 50px auto;
}
hr {
margin: 10px 0;
}
li {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.order {
font-size: 20px;
margin-right: 10px;
}
.title {
margin-right: 10px;
}
.hot {
background: rgb(211, 34, 34);
font-size: 10px;
color: white;
padding: 2px 3px;
border-radius: 5px;
}
.index-1 {
color: rgb(190, 7, 7);
}
.index-2 {
color: rgb(211, 34, 34)
}
.index-3 {
color: rgb(197, 88, 16)
}
<div class="hot-news">
<h2>头条热榜h2>
<hr />
<ul>
<li>
<span class="order index-1">1span>
<span class="title">河北通勤车坠河瞬间曝光span>
<span class="hot">热span>
li>
ul>
div>
let data = [
{
id: 1,
title: "河北通勤车坠河瞬间曝光",
time: "2022-06-27",
is_hot: true, //是否为热门
is_new: false, //是否最新的新闻
},
{
id: 2,
title: "国足公布对阵沙特23人大名单",
time: "2023-06-22",
is_hot: true,
is_new: false,
},
{
id: 3,
title: "“争控”成中印边境谈判关键词",
time: "2023-05-22",
is_hot: true,
is_new: false,
},
{
id: 4,
title: "五粮液独董郎定常因突发疾病去世",
time: "2024-04-22",
is_hot: false,
is_new: false,
},
{
id: 5,
title: "王立科被逮捕:曾想停播人民的名义",
time: "2025-03-22",
is_hot: false,
is_new: true,
},
{
id: 6,
title: "台风“圆规”路径",
is_hot: true,
is_new: false,
time: "2022-07-22",
},
{
id: 7,
title: "保姆报复前雇主偷走其最爱煎锅",
is_hot: true,
is_new: false,
time: "2022-08-22",
},
{
id: 8,
title: "中国南海军事演习引发海外关注",
is_hot: false,
is_new: false,
time: "2022-09-06",
},
{
id: 9,
title: "河北坠河班车已致14人遇难",
is_hot: true,
is_new: false,
time: "2022-10-25",
},
];
综合练习2:-实现评论列表功能
- 如果有评论数据,就展示列表结构 li( 列表渲染 )要包含a标签
- name 表示评论人,渲染 h3
- content 表示评论内容,渲染 p
- 如果没有评论数据,就展示一个 h1 标签,内容为: 暂无评论!
- 用户名的字体25px, 内容的字体20px
- 点击内容区域提示它发表的时间
const list = [
{ id: 1, name: 'jack', content: 'rose, you jump i jump', time: '03:21' },
{ id: 2, name: 'rose', content: 'jack, you see you, one day day', time: '03:22' },
{ id: 3, name: 'tom', content: 'jack,。。。。。', time: '03:23' }
]