01 React入门、虚拟DOM

news2024/11/27 5:32:17

总结

一、React 入门

1.1 特点

高性能、声明式、组件化、单向响应的数据流、JSX扩展、灵活

1.2 React初体验

<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>

1.3 注意事项

  • root.render可以使用多次,但最后一次render会将之前的覆盖掉。
  • 不要同时挂载相同的容器(会报错)
  • 在一个页面中,可以挂载多个不同的容器
  • render中可以渲染的内容类型(数组类型、数值类型、字符串类型)
  • render中不可以渲染的内容类型,会报错 (对象和函数不能渲染,但是函数中可以return让render能渲染的内容类型,json对象字符串可以渲染)
  • render中不会报错,但不会渲染内容的类型
	 //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);
  • 不建议将根容器指定为body元素或html元素(会报错)

二、虚拟DOM

2.1 创建

语法:*React.createElement(标签名,标签属性对象,值)*

标签属性:需要传入一个对象,设置:键值对,不设置:空对象{}或者null

  • 注意:如果想要创建的标签中嵌套其他子标签时

语法:*React.createElement(标签名,标签属性,子节点1,子节点2...)*同级标签
*React.createElement(标签名,标签属性,React.createElement(标签名,标签属性.'内容')* 子标签

  • 包含多个元素:从第三个参数开始即是包裹的内容。或将第三个参数设置为数组,

    如果第三个参数设置为数组,数组元素需要增加唯一key属性

2.2 JSX语法

2.2.1 jsx基本语法

 //6、render可以接收虚拟DOM,会将虚拟DOM转为真实Dom
//6.1 渲染指定元素
// root.render(<div>我是一个DIV</div>)
一个元素包裹多个元素
如果元素是单标签,必须闭合
如果元素较多可以换行,建议这样做添加 ()
JSX中标签必须闭合,单双标签都必须
JSX有且只能是一个根元素
可以使用包裹标签:包裹标签不会被编译(不会渲染),只是起到包裹的作用。
<React.Fragment></React.Fragment>

2.2.2 注释

必须使用 {} 包裹

  • 单行注释 { // 我是注释 }
  • 多行注释 { /* 添加多行注释*/ }

2.2.2 插值表达式

语法 {}
{指定动态的属性值和标签体文本}中填写变量值。

  • 可以是任意基本类型数据值
    • 如果{}内的是用双引号,单引号,反引号包裹,则是字符串;
    • 如果{}内是数字,即是要输出该数字;
    • 如果{}内是undefined,null,true,false不会进行渲染
  • 可以是一个 JS 数组,会直接进行展开渲染(不包含逗号 ), 不允许是对象
  • 可以是 JS 的表达式,不允许在{}内写JS语句
  • 可以是 react 元素对象

2.3.4 条件渲染

在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);

2.3.5 属性渲染

作用:为属性指定数据,可以直接使用{},不需要加双引号

  constimgUrl = "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png"
  const w = 110;
  <img src={imgUrl} width={w} />

2.3.6 列表渲染

react中可以将数组中的元素依次渲染到页面上,可以直接往数组中存储react元素,推荐使用数组的 map 方法

注意:必须给列表项添加唯一的 key 属性, 推荐使用id作为key, 尽量不要用index作为key

  • 数组是可以被直接展开的
  • 数组中的元素也可以是JSX
  • 如果使用map,map接收的是一个箭头函数,{}:如果要返回内容需要使用return,()返回的内容

2.3.7 样式渲染

  • 行内样式(style)
    style属性值是一个对象,
    带有"-"的属性名需要写成驼峰命名
    当属性值单位为px的时候,且值为number类型,可以省略单位,直接写成数值
    <div style={{width: 100,height: '100px', background: 'red',marginLeft: '100px'}}>尚硅谷</div>

  • 非行内样式(className)
    <p className="box">尚硅谷</p>

2.3.7 关于事件

  • 绑定事件

React 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:

React 事件的命名采用小驼峰式(camelCase),而不是纯小写。比如:onClick、onFocus 、onMouseEnter

使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串

const div = <div onClick={事件处理函数}></div>

  • 事件对象

React 根据 W3C 规范来自定义的合成事件, 与原生事件不完全相同

  • 处理好了浏览器的兼容性问题

  • 阻止事件默认行为不能使用 return false, 必须要调用: event.preventDefault()

  • 有自己特有的属性, 比如: nativeEvent – 原生事件对象

  • <input>的 change 监听在输入过程中触发, 而原生是在失去焦点才触发

    原理:内部绑定的是原生 input 事件

在事件对象中属性虽然很多,但是一点要记住的有两点:

  • 1、实际发生事件的目标对象(由于最终虚拟DOM要转换成真实DOM,所以e.target获取的都是真实DOM):e.target
    console.log(e.target)
    console.log(e.target.innerHTML)
  • 2、关于事件默认行为的取消:e.preventDefault()

React全家桶

技术栈:React基本操作+虚拟DOM+函数组件+JSX+类组件+脚手架+Hooks+ajax+路由+UI组件+redux+TS

一、React入门

1.1 简介

img

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/

1.2. 特点

  • 高性能:虚拟DOM(Virtual DOM)配合 diff 算法,最大限度地减少与 DOM 的交互。

  • 声明式:React采用声明式编码UI,可以轻松实现交互式UI,让代码更加可行且方便调试。

    <button onClick="函数">登录</button>
    
  • 组件化:通过 React 构建组件,使得代码更加容易得到复用,能够高效率的应用在大项目的开发中。

  • 单向响应的数据流:React 中的数据是单向自顶向下传递的,父组件数据的更新会自动传递到子组件

    ​ 但子组件的数据更新不会影响到父组件,也不能在子组件修改父组件传入的数据

  • JSX扩展:JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但官网建议使用它。

  • 灵活:React可以与已知的库或框架很好的进行配合。

1.3 国内reactjs开发的项目

  • 腾讯云:https://cloud.tencent.com/
  • 阿里云: https://www.aliyun.com/
  • 七牛云控制中心 https://portal.qiniu.com/create
  • 支付宝商家中心:https://mrchportalweb.alipay.com/user/home
  • MDN: https://developer.mozilla.org/zh-CN/
  • 知乎: https://www.zhihu.com/
  • 美团: https://bj.meituan.com/
  • 飞猪旅行: https://www.fliggy.com/?spm=181.11358650.0.0.6718223eLhsSSU

1.4. 安装版本

安装版本:18.2.0【最新版本】

1.5. React初体验

使用步骤:

  • 引入react核心文件
<script src="./js/react.development.js"></script>
  • 引入react-dom文件
<script src="./js/react-dom.development.js"></script>
  • 创建容器元素
<div id="root"></div>
  • 通过ReactDOM来创建挂载的根容器
const root = ReactDOM.createRoot(document.querySelector("#root"));
  • 通过root.render来指定呈现的内容
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可以使用多次,但最后一次render会将之前的覆盖掉。
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>

  • render中可以渲染的内容类型
<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("<a>尚硅谷</a>");
        //5.2 数值类型
        //root.render(100);
		//注意:虽然写入的值是数字,但是是按照字符串的方式写入
        //5.3 数组类型
        //注意:如果类型是数组,会被直接展开(无逗号)
        root.render([1, 2, 3, 4])
    </script>
</body>

  • render中不可以渲染的内容类型 (对象和函数不能渲染)
<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.

  • render中不会报错,但不会渲染内容的类型
<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元素或html元素
<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

2.1 什么是虚拟DOM

虚拟DOM的本质是一个普通对象,虚拟DOM的属性会与真实DOM的属性一一对应,虚拟DOM是轻量级的;

真实DOM是重量级的,虚拟DOM最终都会通过React转为真实DOM进行渲染;React操作的都是虚拟DOM。

虚拟DOM元素的创建有两种方式:

  • 通过React.createElement创建(了解)
  • JSX(重点中的重点)–javascript xml 是JS的一个扩展。XML可扩展的标记语言

浏览器向服务器发送请求(请求报文),服务器会给予浏览器响应报文,浏览器会将接收到的响应体中的内容进行

渲染,在进行渲染的过程中如果有CSS,会将CSS进行解析,往往也会加载JS,如果JS对页面结构进行操作的话有可

能产生重排重绘,那么具体什么是重排重绘呢?

重排:

  • 当JS对样式进行几何(位置,大小)操作时,会影响到其它的元素,受影响的元素会重新计算自己的位置

重绘:

  • 重排之后会进行渲染,该渲染称为重绘。

    例如:

    this.style.width = “100px”;
    this.style.height= “200px”;

而通过虚拟DOM,可以大大减少重排重绘。

2.2 创建虚拟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: 属性特别多 ==> 较重的对象
  • ReactDOM.render方法:将虚拟DOM转换为真实DOM再插入页面
  • 如果要呈现较复杂的结构时,用createElement创建很麻烦,且效率低,阅读性差。
  • 在开发过程中不建议使用React.createElement创建虚拟DOM元素,建议使用JSX。

虚拟 DOM 对象包含了对应的真实 DOM 的关键信息属性。

属性示例
标签名type: “h1”
标签属性props: {title: ‘你好, React!’}
子节点props: {children: ‘Hello React!’}

2.3 JSX(重点)

2.3.1 JSX的基本语法

问题: 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>我是一个DIV</div>)

        //6.2  一个元素包裹多个元素
        // root.render(<div><span>1</span><p>2</p></div>);

		//6.3 如果元素是单标签,必须闭合
		//常见的单标签,例如:img、br、hr、input等
		root.render(<div><br/></div>);

        //6.4  如果元素较多可以换行,但不建议这样做:
        // root.render(
        //     <div>
        //         <span>1</span>
        //         <p>2</p>
        //     </div>
        // )

        //6.5  如果元素较多可以换行,建议这样做:
        // root.render(
        //     (
        //         <div>
        //             <span>1</span>
        //             <p>2</p>
        //         </div>
        //     )
        // )

        //6.6 JSX必须闭合
        // root.render(<div></div>);// 正确
        // root.render(<div />);// 正确
        // root.render(<div>);// 不正确

        //6.7 JSX有且只能是一个根元素,以下这种写法不允许
        // root.render(
        //     (
        //         <div>1</div>
        //         <div>2</div>
        //     )
        // )

        // 以下可以解决问题,我们一般会选择可以包含所有行标签和块标签的元素来作为唯一的根元素
        // root.render(
        //     (
        //         <div>
        //             <div>1</div>
        //             <div>2</div>
        //         </div>
        //     )
        // )

        //6.8 可以使用包裹标签:包裹标签不会被编译(不会渲染),只是起到包裹的作用。
        //<React.Fragment></React.Fragment>
        // root.render(
        //     (
        //         <React.Fragment>
        //             <div>1</div>
        //             <div>2</div>
        //         </React.Fragment>
        //     )
        // )

        //对React对象进行解构赋值:首字大写的标签会被作为组件使用。
        // const { Fragment } = React;
        // root.render(
        //     (
        //         <Fragment>
        //             <div>1</div>
        //             <div>2</div>
        //         </Fragment>
        //     )
        // )

        //6.9 后期我们一般会将JSX结构单独定义出来,常量或者变量均可,主要为了方便后期定义组件
        // const vDOM = <div>
        //     <div>3</div>
        //     <p>4</p>
        // </div>
        // 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>
                {
                    //我是单行注释
                }
                {
                    /*
                     * 我
                     * 是
                     * 多
                     * 行
                     * 注
                     * 释
                    */
                }
                {
                    // <p>1</p>
                    // <p>2</p>
                    // <p>3</p>
                }
                {
                    /*
                     * <p>1</p>
                     * <p>2</p>
                     * <p>3</p>
                    */
                }
                {/* 注释内容 */}
            </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>
            {/* 
                <p>{obj}</p>
                <p>{{ a: 1, b: 2 }}</p>
            */}
        </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((
        //     <div>
        //         {arr}
        //     </div>
        // ));
        //6.2 数组中的元素也可以是JSX
        // let arr = [
        //     <span key={0}>1</span>,
        //     <span key={1}>2</span>,
        //     <span key={2}>3</span>,
        //     <span key={3}>4</span>
        // ]
        // root.render((
        //     <div>
        //         {arr}
        //         <span key={0}>1</span>
        //         <span key={1}>2</span>
        //         <span key={2}>3</span>
        //         <span key={3}>4</span>
        //     </div>
        // ));
        //6.3 如果使用map,map接收的是一个箭头函数,明白{},()的区别
        let arr = [1, 2, 3, 4];
        //匿名函数
        /* let arr1 = arr.map(function (item, index) {
            // return <span key={index}>{item}</span>
            return (
                <span key={index}>{item}</span>
            )
        })
        console.log(arr1);
        root.render(arr1); */

        //箭头函数
        // let arr2 = arr.map((item, index) => {
        //     return (
        //         <span key={index}>{item}</span>
        //     )
        // })
        // 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((
        //     <div style="width:100px;height:100px;background:red">尚硅谷</div>
        // ));
        //报错: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((
        //     <div style={{
        //         width: '100px',
        //         height: '100px',
        //         background: 'red'
        //     }}>尚硅谷</div>
        // ));

        //3、带有"-"的属性名需要写成驼峰命名
        // root.render((
        //     <div style={{
        //         width: '100px',
        //         height: '100px',
        //         background: 'red',
        //         marginLeft: '100px'
        //     }}>尚硅谷</div>
        // ));


        //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 – 原生事件对象

  • <input>的 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">1</span>
            <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' }
]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/665230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AIDA64压力测试教程,AIDA64压力测试多长时间,AIDA64压力测试结果怎么看

硬件管理工具AIDA64功能全面专业&#xff0c;操作简便易学&#xff0c;使用AIDA64进行系统稳定性测试逐渐成为更多用户的选择。可能有很多用户对如何使用AIDA64进行系统稳定性测试不太了解&#xff0c;系统稳定性测试也称为压力测试&#xff0c;或者更通俗的烤机测试&#xff0…

SPI协议详细总结附实例图文讲解通信过程(快速掌握)

目录 一、简介二、数据通信过程2.1 通信总过程总结2.2 具体协议规则2.2.1 时钟极性与时钟相位2.2.2 SPI模式2.2.3 图文实例讲解 2.3 SPI协议优缺点总结 三、其他相关链接 一、简介 SPI(Serial Peripheral nterface&#xff0c;串行外设接口) 协议是一种高速高效率、全双工的通…

数据库SQL Server实验报告 之 SQL数据库的安全性(7/8)

实验名称 数据库的安全性实验 注意&#xff1a;原版word在下载资源里面&#xff08;免费下载&#xff09; 实验目的及要求&#xff1a; 使学生加深对数据库安全性和完整性的理解。掌握SQL Server中有关用户、角色及操作权限…

【Android复习笔记】ARouter / Navigation / EventBus

注:本文主要基于过去 Android View 体系的路由学习笔记整理,不包括最新的 Jetpack Compose 路由体系,如您需了解关于 Jetpack Compose 中的导航路由,请参考 Jetpack Compose 中的导航路由 一文。 传统路由方式 // 显性意图 startActivity(new Intent(this, HomeActivity.c…

JavaScript 的性能分析与提升

JavaScript 的性能分析与提升 对于 JavaScript/前端来说&#xff0c;性能的提升主要有两大方面&#xff1a; 页面初始化的优化 这一方面主要涉及到非代码结构上&#xff0c;但是能够提升用户体验感的优化&#xff0c;如&#xff0c;提升用户看到页面的速度、减少用户等待与页面…

一、枚举类型——使用接口来组织枚举

枚举类型无法被继承&#xff0c;这一点可能有时会让人沮丧。想要继承枚举的动机&#xff0c;一部分源自希望扩充原始枚举中的元素&#xff0c;另一部分源自想要使用子类型来创建不同的子分组。 你可以在一个接口内对元素进行分组&#xff0c;然后基于这个接口生成一个枚举&…

Python零基础入门(三)——基本输入与输出

系列文章目录 个人简介&#xff1a;机电专业在读研究生&#xff0c;CSDN内容合伙人&#xff0c;博主个人首页 Python入门专栏&#xff1a;《Python入门》欢迎阅读&#xff0c;一起进步&#xff01;&#x1f31f;&#x1f31f;&#x1f31f; 码字不易&#xff0c;如果觉得文章不…

关于 Vue3 响应式 API 以及 reactive 和 ref 的用法

文章目录 &#x1f4cb;前言&#x1f3af;关于响应式&#x1f3af;reactive 的用法&#x1f3af;ref 的用法&#x1f4dd;最后 &#x1f4cb;前言 这篇文章记录一下 Vue3 响应式的内容&#xff0c;其中还包括了 reactive 和 ref 的用法。响应式是一种允许以声明式的方式去适应…

VMware16虚拟机安装Ubuntu16.04 LTS

VMware14虚拟机安装Ubuntu16.04 LTS 一、基本介绍二、vmware下安装ubuntu系统2.1 下载ubuntu客户端镜像2.2 安装及配置2.2.1 安装2.2.2 配置 三、ubuntu系统使用 回到目录   回到末尾 一、基本介绍 对于ubuntu而言&#xff0c;就是linux操作系统的具体&#xff0c;而linux对…

S7-1200通过外部端子控制V20变频器启停+MODBUS读写频率的具体方法

S7-1200通过外部端子控制启停+MODBUS读写频率的具体方法 本例中是通过S7-1200PLC外部端子的方式控制变频器启停,用Mobus RTU通讯读写变频器频率。 硬件连接: 屏蔽双绞线将V20变频器P+,N-连接到CPU上CB1241 T/RA 和T/RB, T/RB接P+,T/RA接N-。TA和T/RA用短线连上,TB和T/RB用短…

jmeter函数助手

详解JMeter函数和变量 测试人员可以在JMeter的选项菜单中找到函数助手对话框&#xff08;"Function Helper"对话框&#xff09;&#xff0c;如图11-1所示。 图11-1 函数助手&#xff08;Function Helper&#xff09;对话框 使用函数助手&#xff0c;测试人员可以…

【Python】文件操作 ② ( 文件操作 | 读取文件 | read 函数 | readline 函数 | readlines 函数 )

文章目录 一、读取文件1、read 函数2、readline 函数3、readlines 函数 二、代码示例 - 读取文件1、代码示例 - read 函数读取文件 10 字节内容2、代码示例 - read 函数读取文件所有内容3、代码示例 - readline 函数读取文件一行内容4、代码示例 - readlines 函数读取文件所有内…

利用 AI 作图帮助理解知识

一、背景 人类对图形的接受和处理能力高于对文字和数字的处理能力。 如果我们学习某个知识的时候&#xff0c;能够找到配套的图&#xff0c;理解会好很多。 但&#xff0c;并不是所有的知识都有配图。 然而&#xff0c;人工智能的时代已经来临&#xff0c;为什么不尝试用 AI…

Flutter 项目创建、运行及结构分析

目录 开发工具 创建项目 1.New Flutter Project 1.1直接创建新项目 1.2 已有项目创建新项目 2.选择SDK&#xff0c;补充项目资料 3.Demo已生成 3.1 android 目录 3.2 ios目录 3.3 lib目录 3.4 test 目录(可先不管) 4.配置文件 4.1 pubspec.yaml文件 4.2 pubspec.lock 4…

chatgpt赋能python:Python报错重新执行技巧

Python报错重新执行技巧 如果你在使用Python编程时&#xff0c;经常遇到报错的情况&#xff0c;特别是在大量数据处理或者复杂算法实现时&#xff0c;报错更是常态。那么&#xff0c;你是否不知道该如何处理这些报错信息&#xff0c;或者对于重新执行代码有一些不确定的想法&a…

【Leetcode60天带刷】day15二叉树——102. 二叉树的层序遍历 ,226.翻转二叉树 ,101.对称二叉树 2

题目&#xff1a; 102. 二叉树的层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],…

嵌入式系统课程设计——温度记录仪

课程设计目录 一、嵌入式系统基础实验 二、项目需求分析 三、实验方案设计 四、实验程序设计 五、成本核算情况 八、完成情况与问题分析 九、学习心得 一、嵌入式系统基础实验 1.1实验平台的使用 图1 建立新工程图片 图2 选择lpc1114芯片图片 图3 选择头文件图片 图4 编译…

基于51单片机数字频率计的设计与实现

目录 第一章 系统原理与总体设计 1.1系统组成 1.2系统原理 1.3测量原理 1.4频率测量与总体设计 第二章 硬件电路设计 2.1硬件电路框图 2.2数字频率计原理图 2.3硬件电路设计 第三章 软件程序设计 3.1程序流程图 3.2显示电路程序设计 3.3 定时器初始化程序设计 3.4…

MeetingService重构和ParticipantList性能优化实践

​ 一丶背景 1.1 现状 最初Rooms客户端只支持加入Rcv meeting这个meeting type&#xff0c;RcvMeetingStateService里写了一些加会的状态机转换和Audio, Video, Share相关的功能代码。后续有新的业务&#xff0c;需要增加支持Webinar, Sip等各种Meeting&#xff0c;MeetingS…

Linux Shell 实现一键部署ovirt4

ovirt 前言 oVirt是一个开源分布式虚拟化解决方案&#xff0c;旨在管理您的整个企业基础设施。oVirt使用可信的KVM管理程序&#xff0c;并基于其他几个社区项目构建&#xff0c;包括libvirt、Gluster、PatternFly和Ansible。 Ovirt仅支持系统Centos / Redhat ovirt download…