01 React入门、虚拟DOM

总结

一、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' }
]

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件 安全,处理威胁STRIDE模型

微软威胁分析工具&#xff1a; https://www.microsoft.com/en-us/securityengineering/sdl/threatmodeling?azure-portaltrue STRIDE 是微软定义的6中威胁 身份假冒&#xff08;Spoofing&#xff09; 身份假冒&#xff0c;即伪装成某对象或某人。例如&#xff0c;我们通过伪…

1-简单回归问题

一.梯度下降&#xff08;gradient descent&#xff09; 1.预测函数 这里有一组样本点&#xff0c;横纵坐标分别代表一组有因果关系的变量 我们的任务是设计一个算法&#xff0c;让机器能够拟合这些数据&#xff0c;帮助我们算出参数w 我们可以先随机选一条过原点的直线&#xf…

无人机电池能不能上高铁以及什么型号的电池可以上高铁

无人机电池能不能上高铁以及什么型号的电池可以上高铁 高铁关于电池的限制电池参数介绍可上高铁的无人机锂电池6S电池3S电池 高铁关于电池的限制 2022年7月1日起施行的《铁路旅客禁止、限制携带和托运物品目录》规定,充电宝、锂电池单块额定能量不超过100Wh 电池参数介绍 明…

HarmonyOS学习路之开发篇—Java UI框架(DependentLayout)

DependentLayout DependentLayout是Java UI框架里的一种常见布局。与DirectionalLayout相比&#xff0c;拥有更多的排布方式&#xff0c;每个组件可以指定相对于其他同级元素的位置&#xff0c;或者指定相对于父组件的位置。 支持的XML属性DependentLayout的共有XML属性继承自…

SpringBoot不在使用@Validated 做参数校验但是不想在Controller层怎么办?

目录 场景再现&#xff1a; 怎么做&#xff1f; 遇到了什么问题&#xff1f; 怎么实现&#xff1f; 场景再现&#xff1a; 某API接口接受加密的json字符串&#xff0c;接受字符串之后先进行解密处理&#xff0c;解密完成之后还要进行参数校验处理&#xff0c;如果参数不合规…

使用 TensorFlow.js 将机器学习引入您的 Web 应用程序

如何使用 TensorFlow.js 在您的 Web 应用程序中实施机器学习 原文作者: Abhay Singh Rathore 机器学习 (ML) 不再是一个崇高、遥不可及的概念。借助 TensorFlow.js 等库&#xff0c;开发人员现在可以将 ML 整合到他们的 Web 应用程序中。例如&#xff0c;您可以创建一个系统&am…

Springcloud之Feign、Hystrix、Ribbon如何设置超时时间

一&#xff0c;概述 我们在微服务调用服务的时候&#xff0c;会使用hystrix、feign和ribbon&#xff0c;比如有一个实例发生了故障而该情况还没有被服务治理机制及时的发现和摘除&#xff0c;这时候客户端访问该节点的时候自然会失败。 所以&#xff0c;为了构建更为健壮的应…

美味度配方

8 种配料每种配料可以放 1 到 5 克&#xff0c;美味度为配料质量之和&#xff0c;给定一个美味度 n&#xff0c;求解 8 种配料的所有搭配方案及方案数量 。 (本笔记适合学了 Python 循环&#xff0c;正在熟炼的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a…

prisma 学习记录

1、prisma 可以看做是一个 ORM。 安装 prisma npm install prisma -D 初始化 prisma , 并设置要链接的数据库 npx prisma init --datasource-provider sqlite --datasource-provider 要使用的数据库 2、prisma 中的模型&#xff0c; 表示底层数据库中的表或者集合。 生成 Pri…

Baumer工业相机堡盟工业相机如何使用BGAPISDK的相机图像时间戳计算运行时间以及时间差(C++)

Baumer工业相机堡盟工业相机如何使用BGAPISDK的相机图像时间戳计算运行时间以及时间差&#xff08;C&#xff09; Baumer工业相机Baumer工业相机BGAPI SDK和图像时间戳的技术背景Baumer工业相机使用BGAPISDK控制相机数据流的方式1.引用合适的类文件2.使用BGAPISDK获取时间戳的方…

shell脚本进阶1——精读ansible+shell脚本

文章目录 一、脚本规划思路二、主控机shell脚本2.1 脚本输出字体特效2.2 生成菜单栏对话框2.3 配置本地yum源仓库2.4 配置受控机yum源2.5 关闭防火墙和selinux2.6 把docker安装包给受控机2.7 安装docker-compose2.8 安装docker2.9 安装ansible2.10 安装pip2.11 主控本机免密登录…

利用谷歌DevTool解决web网页内存泄漏问题

目录 web网页内存泄漏 主要的内存泄漏来源 利用谷歌DevTool定位内存泄漏问题 性能Performance 主要功能 Performance insights性能数据分析 Memory内存 三种模式 相关概念 解决内存泄漏问题 第一步 &#xff1a;是否内存泄漏&#xff1a;js堆直增不降&#xff1b;降…

Unity3d_Cut\Clipping sphere\CSG(boolean)(裁剪模型重合部分)总结

1、https://liu-if-else.github.io/stencil-buffers-uses-in-unity3d/ 下载&#xff1a;https://github.com/liu-if-else/UnityStencilBufferUses 2、手动切割 Unity 模型切割工具,CSG,任意图案,任意切割_unity csg_唐沢的博客-CSDN博客 3、 Shader Unity Shader学习&#x…

CVPR 2023 | 计算机视觉顶会亮点前瞻

在知识和技术都迅速更新迭代的计算机领域中&#xff0c;国际计算机视觉与模式识别会议&#xff08;CVPR&#xff09;是计算机视觉方向的“顶级流量”&#xff0c;引领着学科及相关领域的研究潮流。今天我们为大家带来5篇微软亚洲研究院被 CVPR 2023 收录的论文&#xff0c;主题…

JVM知识点梳理

什么是JVM&#xff1f; JVM是java虚拟机的缩写 &#xff0c;也是java程式可以实现跨平台的关键。 JVM部分需要知道什么东西&#xff1f; JVM的结构和功能、参数配置、GC回收机制、GC回收器极其优缺点。 JVM结构&#xff08;栈&#xff0c;程序计数器&#xff0c;方法区&#xf…

基于深度学习的高精度打电话检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度打电话检测识别系统可用于日常生活中或野外来检测与定位打电话目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的打电话目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检…

《C# 教程》菜鸟教程学习笔记

学习地址 ######C#有用的网站 C# Programming Guide - 介绍了有关关键的 C# 语言特征以及如何通过 .NET 框架访问 C# 的详细信息。Visual Studio - 下载作为 C# 集成开发环境的 Visual Studio 的最新版本。Go Mono - Mono 是一个允许开发人员简单地创建跨平台应用程序的软件平台…

【每日算法】【203. 移除链表元素】

☀️博客主页&#xff1a;CSDN博客主页 &#x1f4a8;本文由 我是小狼君 原创&#xff0c;首发于 CSDN&#x1f4a2; &#x1f525;学习专栏推荐&#xff1a;面试汇总 ❗️游戏框架专栏推荐&#xff1a;游戏实用框架专栏 ⛅️点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd;&…

Docker基本介绍

一、定义 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。 解决了运行环境和配置问题的软件容器&#xff0c; 方便做持续集成并有助于整…

UnityVR--UIManager--UI管理1

目录 前言 UI节点的结构 需要用到的组件 1. CanvasGroup 2. Button等控件的OnClick()监听 3. EventTrigger 建立UI工具集 1. 管理UI节点 2. UIBase包含了以下的工具 建立分面板的管理工具——以主面板MainUi为例 前言 UI在项目中的重要性不言而喻&#xff0c;并且UI控件的…