React一学就会(4): 强化练习二

news2024/11/17 3:08:53

书接上回,是不是感觉已经有点入门了。不过别急,码哥我准备了很多干货,等我们把这些基本几个章节的学完,码哥带着你一起装逼一起飞。我不大可能只是带着你们入门,那不是我的风格。码哥会教你如何开发一个完整中后台。前端后端如何匹配,什么安全什么策略都会教给你。如果你还有其它兴趣,我还可以教你许多网络知识,Android开发、IOS开发,Mac开发、
c#开发等等。总之,一年的时间你肯定学不完。根本学不完。

条件渲染

一句话,根据某种条件做出不同的渲染元素。所谓的条件就是各种判断,if 也好 三目运算符也好。都行
比如,下面的两个用户组件:
为了美观,下面所有的示例中我统一用MUI的样式组件,关于MUI的安装我在第一节课就已经讲过了,如果你是从第一节学过来的,应该没什么问题。

// Users.jsx
import Typography from '@mui/material/Typography';

function UserGreeting(props) {
    return <Typography variant="h1" gutterBottom> 欢迎回来!</Typography>;
}

function GuestGreeting(props) {
    return <Typography variant="h1" gutterBottom>请登录.</Typography>;
}

export { UserGreeting, GuestGreeting };

现在我们要创建一个新的组件,这个组件的功能是根据用户登录的条件来显示其中一个组件。 我们来创建Greeging组件如下:

//Greeting.jsx
import { UserGreeting, GuestGreeting } from "./Users";

export default function Greeting(props) {
    const isLoggedIn = props.isLoggedIn;
    if (isLoggedIn) {
        return <UserGreeting />;
    }
    return <GuestGreeting />;
}

你看,这个最基本的条件渲染组件就完成了。很简单是不是,当然,我们还可以把条件弄的复杂一点:

元素变量

所谓元素变量就是把一个组件元素存储在一个变量中,渲染时直接渲染这个变量就可以了
比如有下面两个组件,一个是登录组件 LoginButton,一个是登出组件 LogoutButton

// logButtons.jsx
import Button from "@mui/material/Button";

function LoginButton(props) {
    return (
        <Button variant="outlined" onClick={props.onClick}>
            登录
        </Button>
    );
}

function LogoutButton(props) {
    return (
        <Button variant="outlined" onClick={props.onClick}>
            退出
        </Button>
    );
}

export { LoginButton, LogoutButton };

接下来我们创建一个有状态的组件,根据上面两个按钮点击的结果显示不同的界面。

// LoginControl.jsx
import React from 'react';
import { LoginButton, LogoutButton } from './LogButtons';
import Greeting from './Greeting';
import Box from '@mui/material/Box';

class LoginControl extends React.Component {
    constructor(props) {
        super(props);
        this.state = { isLoggedIn: false };

        //在构造函数中我们采用先绑定this的方法与事件绑定
        this.handleLoginClick = this.handleLoginClick.bind(this);
        this.handleLogoutClick = this.handleLogoutClick.bind(this);
    }

    handleLoginClick() {
        this.setState({ isLoggedIn: true });
    }

    handleLogoutClick() {
        this.setState({ isLoggedIn: false });
    }

    render() {
        const isLoggedIn = this.state.isLoggedIn;
        let button;
        if (isLoggedIn) {
            button = <LogoutButton onClick={ this.handleLogoutClick } />;
        } else {
            button = <LoginButton onClick={ this.handleLoginClick } />;
        }

        return (
            <Box>
                <Greeting isLoggedIn={isLoggedIn} />
                {button}
            </Box>
        );
    }
}

export default LoginControl;

至于为什么我这里不用函数组件的方式写这个 LoginControl 组件呢,因为我们还有很多Hook没有学习。当我们学习了所有的相关知识后,你就可以想怎么写就怎么写了。
上面的逻辑已经很清晰了,不用多讲什么了吧。
下面我们在App.jsx中调用这个组件就OK了,是不是很Nice,有点小激动不。

//App.jsx
import './App.css'
import "./styles.css";
// import Profile from './Profile'
// import ButtonClickTest from './buttonClickTest';
// import MyCompButton from './Test03/MyButtons';
// import Counter from './Test03/ClassComponentTest';
// import Clock from './Test03/Clock';
// import ClockFunc from './Test03/ClockFunc';
import LoginControl from './Test04/LoginControl';

function App() {
  return (
    <LoginControl />
  )
}

export default App
关于 && 及 || 的渲染应用示例。

先看下面的示例

// Mailbox.jsx
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";

export default function Mailbox(props) {
    const unreadMessages = props.unreadMessages;
    return (
        <Box>
            <Typography variant="h1">你好!</Typography>
            {
                unreadMessages.length > 0 &&
                <Typography variant="h2">
                    你有 {unreadMessages.length} 条未读消息。
                </Typography>
            }
        </Box>
    );
}

这个时候如果我们直接在App.jsx中调用这个组件,什么也不会显示。但我们给 unreadMessages 传递两条信息就不一样了

//App.jsx
import './App.css'
import "./styles.css";
// import Profile from './Profile'
// import ButtonClickTest from './buttonClickTest';
// import MyCompButton from './Test03/MyButtons';
// import Counter from './Test03/ClassComponentTest';
// import Clock from './Test03/Clock';
// import ClockFunc from './Test03/ClockFunc';
// import LoginControl from './Test04/LoginControl';
import Mailbox from './Test04/Mailbox';

function App() {
  return (
    <Mailbox unreadMessages={["message1", "message2"]} />
  )
}

export default App

是不是有点意思。
其实 条件 && 组件 的意思是 当条件为真时才渲染组件, 这就是 && 的用法。类似的 || 的用法是这样的:
变量 || 组件 表示当变量不为null时,就显示 变量,当变量为 null 时,就显示 组件。我们也常常用 || 变量提供一个备选值。

不有三目运算符的用法:
我们把上面 组件 Greeting 修改一下:

import { UserGreeting, GuestGreeting } from "./Users";

export default function Greeting(props) {
    const isLoggedIn = props.isLoggedIn;
    return (
        <Box>
        {
            isLoggedIn
            ? <UserGreeting /> 
            : <GuestGreeting />
        }
        </Box>
    )
}

这样更直观一点。

阻止组件渲染

有时候我们希望在某种情况下我们的组件不要渲染出来。我们在 html 中用 css 可以设置隐藏组件,但它还是在文档流中,只是被隐藏了。但在我们的React中可以让它真正的消失,要达到这种效果,我们只要在组件中返回 null 即可。

//Page.jsx
import { Component } from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';

function WarningBanner(props) {
    return (
        props.warn
            ? <Box className="warning"> 警告! </Box>
            : null
    );
}

class Page extends Component {
    constructor(props) {
        super(props);
        this.state = { showWarning: true };
        this.handleToggleClick = this.handleToggleClick.bind(this);
    }

    handleToggleClick() {
        this.setState(state => ({
            showWarning: !state.showWarning
        }));
    }

    render() {
        return (
            <Box>
                <WarningBanner warn={this.state.showWarning} />
                <Button variant="contained" onClick={this.handleToggleClick}>
                    {this.state.showWarning ? '隐藏' : '显示'}
                </Button>
            </Box>
        );
    }
}

export default Page;

上面我们定义了两个组件 WarningBannerPage, Page组件中根据按钮点击后的的状态显示 WarningBanner
在 App.jsx中调用一下查看结果

import './App.css'
import "./styles.css";
// import Profile from './Profile'
// import ButtonClickTest from './buttonClickTest';
// import MyCompButton from './Test03/MyButtons';
// import Counter from './Test03/ClassComponentTest';
// import Clock from './Test03/Clock';
// import ClockFunc from './Test03/ClockFunc';
// import LoginControl from './Test04/LoginControl';
// import Mailbox from './Test04/Mailbox';
import Page from './Test04/Page';

function App() {
  return (
    <Page />
  )
}

export default App

列表

我们来看看 JavaScript 中的数组遍历, 在控制台查看结果。

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled);

在 React 中有时显示多个元素时也是用这个方法,如

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li> { number } </li>
);
基本列表

如下示例:

// NumberList.jsx
export default function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <li>{number}</li>
  );
  return (
    <ul> { listItems } </ul>
  );
}

如果用的是VSCode,那么这时候应该有一个语法警告提示,我们先不管它。
我们在App.jsx中调用并传入props参数

import './App.css'
import "./styles.css";
import NumberList from './Test04/Numbers';

function App() {
  return (
    <NumberList numbers = {[1, 2, 3, 4, 5, 6]} />
  )
}

export default App

此时运行,你会发现在控制台会有一条警告提示信息:
在这里插入图片描述

意思是列表元素少了 key 这个属性。React要求,所有列表元素都必须要用 key 属性,它可以帮助 React 识别哪些项目已更改、添加或删除。应该为数组中的元素提供 key,以使元素具有稳定的标识, 我们修改如下:

const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);

const todoItems = todos.map((todo, index) =>
  <li key={index}>
    {todo.text}
  </li>
);

确保每个列表项的key为唯一即可。 还有一点要注意的是我们不应该把 key 直接写入组件,比如下面的做法是错误的。

function ListItem(props) {
  const value = props.value;
  return (
    // 错误,这里直接把key写到元素上了,li 原始元素并没有这个属性。
    <li key={value.toString()}>
      {value}
    </li>
  );
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    // 错误。我们应该在这里为React组件指定key
    <ListItem value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

正确的做法是这样的:

function ListItem(props) {
  // 相当OK, 这里不需要指定 key, 
  return <li>{props.value}</li>;
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    // 完全OK, 在这里我们为React组件指定了Key。 key是React内部使用,跟我们如何定义组件并没有多大的关联。数组列表我们额外加上就行了。
    <ListItem key={number.toString()} value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

还有一点要注意,这个key 只要在同级之前是唯一的就行。如果列表内嵌套列表,子列表的 key 和外层的key即使相同也不冲突。像下面的示例

// Blog.jsx
export default function Blog(props) {
  const sidebar = (
    <ul>
      {props.posts.map((post) =>
        <li key={post.id}>
          {post.title}
        </li>
      )}
    </ul>
  );
  const content = props.posts.map((post) =>
    <div key={post.id}>
      <h3>{post.title}</h3>
      <p>{post.content}</p>
    </div>
  );
  return (
    <div>
      {sidebar}
      <hr />
      {content}
    </div>
  );
}

调用并运行它,我们会发现一切正常

import './App.css'
import "./styles.css";
import Blog from './Test04/Blog';

const posts = [
  { id: 1, title: 'Hello World', content: 'Welcome to learning React!' },
  { id: 2, title: 'Installation', content: 'You can install React from npm.' }
];

function App() {
  return (
    <Blog posts={posts} />
  )
}

export default App

当前也可以直接在JSX中嵌入map

function NumberList(props) {
  const numbers = props.numbers;
  return (
    <ul>
      {numbers.map((number) =>
        <ListItem key={number.toString()}
                  value={number} />
      )}
    </ul>
  );
}

是不是感觉清爽多了。

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

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

相关文章

知识增强系列 ERNIE: Enhanced Representation through Knowledge Integration,论文解读

论文全称&#xff1a;通过知识集成增强语义表达 1. motivation ERNIE 目的在于通过知识屏蔽策略增强语言表示&#xff0c;其中屏蔽策略包括实体级屏蔽(Entity-level strategy)和短语级屏蔽(Phrase-level strategy)。 entity-level 策略通常会掩盖由多个单词组成的实体; Phrase…

智能加湿器数据分析:预计2025年市场规模将达到164.18亿元

随着经济的发展和人民生活水平的提高&#xff0c;人们对生活质量和健康的要求愈来愈高。空气加湿器慢慢的走进家庭当中&#xff0c;预计2023年中国线上超声波加湿器零售额同比下降4.9%;线上纯净型加湿器零售额同比增长44.8%。随着社会科技的不断进步和居民消费水平的不断提高&a…

【网络】WireShark过滤 | WireShark实现TCP三次握手和四次挥手

目录 一、开启WireShark的大门 1.1 WireShark简介 1.2 常用的Wireshark过滤方式 二、如何抓包搜索关键字 2.1 协议过滤 2.2 IP过滤 ​编辑 2.3 过滤端口 2.4 过滤MAC地址 2.5 过滤包长度 2.6 HTTP模式过滤 三、ARP协议分析 四、WireShark之ICMP协议 五、TCP三次握…

容器和虚拟机的对比

容器和虚拟机的对比 容器和虚拟机在与硬件和底层操作系统交互的方式上有所不同 虚拟化 使多个操作系统能够同时在一个硬件平台上运行。 使用虚拟机监控程序将硬件分为多个虚拟硬件系统&#xff0c;从而允许多个操作系统并行运行。 需要一个完整的操作系统环境来支持该应用。…

Rust循环和函数

下面聊聊以下主题&#xff1a; 基于条件的分支循环函数属性测试 基于条件的分支 基于条件的分支&#xff0c;可以通过常见的 if、if else 或 if else if else 构造来完成&#xff0c;例如下面的示例&#xff1a; fn main() { let dead false; let health 48; if dead { p…

JVM问题排查手册

三万字长文&#xff1a;JVM内存问题排查Cookbook 一、Heap快照 # jmap命令保存整个Java堆&#xff08;在你dump的时间不是事故发生点的时候尤其推荐&#xff09; jmap -dump:formatb,fileheap.bin <pid> # jmap命令只保存Java堆中的存活对象, 包含live选项&#xff0c;…

golang:beego的简单介绍和TiDB数据库的客户端实现

查阅官方文档和源码可以知道&#xff0c;beego库中有一个orm包负责数据库接口的封装。这个包支持若干个数据库引擎&#xff1a; 看到了一个文档&#xff0c;对ORM(Object-Relational Mapping)这个东西解释得比较清楚&#xff1a; 具体的客户端实现见下&#xff1a; package …

【JavaScript基础入门】04 JavaScript基础语法(二)

JavaScript基础语法&#xff08;二&#xff09; 目录 JavaScript基础语法&#xff08;二&#xff09;变量变量是什么声明变量变量类型动态类型注释 数字与运算符数字类型算术运算符操作运算符比较运算符逻辑运算符运算符的优先级 变量 变量是什么 在计算机中&#xff0c;数据…

Cesium 问题:遇到加载Cesium时各组件飞出

致敬爱的读者&#xff1a;该问题出现后暂时未找到最优的解决方案&#xff0c;而是将所有组件状态均进行隐藏&#xff0c;大家如果有解决方案可以留言、评论大家一起探讨解决&#xff0c;欢迎大家踊跃说出自己的想法 文章目录 问题分析 问题 在加载 Cesium 时出现各组件的位置不…

HarmonyOS模拟器启动失败,电脑蓝屏解决办法

1、在Tool->Device Manager管理界面中&#xff0c;通过Wipe User Data清理模拟器用户数据&#xff0c;然后重启模拟器&#xff1b;如果该方法无效&#xff0c;需要Delete删除已创建的Local Emulater。 2、在Tool->SDK Manager管理界面的PlatForm选项卡中&#xff0c;取消…

云畅科技入选国家超级计算长沙中心生态合作伙伴

为更好地服务国家战略和区域经济社会高质量发展&#xff0c;打造数据驱动经济发展的新态势&#xff0c;国家超级计算长沙中心面向全国开展了生态合作伙伴的征集工作。经企业申报、专家评审等环节&#xff0c;湖南云畅网络科技有限公司顺利通过审核&#xff0c;成功入选“国家超…

面试经典150题——找出字符串中第一个匹配项的下标

找出字符串中第一个匹配项的下标 思路分析&#xff1a; 思路一&#xff1a;直接调用String的API&#xff1a;indexOf 大道至简&#xff0c;String中的IndexOf是这样描述的&#xff1a; /*** Returns the index within this string of the first occurrence of the* specified…

牛客——小红又战小紫(概率dp和逆元)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 小红上次输给了小紫&#xff0c;表示不服&#xff0c;于是又约来小紫来玩一个游戏。 这次是取石子游戏&#xff1a;共有nnn堆石子&#xff0c;两人轮流使用以下两种技能中的一种进行取石子&#x…

如何在Win系统安装Jupyter Notbook并实现无公网ip远程访问本地笔记

文章目录 1.前言2.Jupyter Notebook的安装2.1 Jupyter Notebook下载安装2.2 Jupyter Notebook的配置2.3 Cpolar下载安装 3.Cpolar端口设置3.1 Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 在数据分析工作中&#xff0c;使用最多的无疑就是各种函数、图表、…

《WebKit 技术内幕》学习之十四(1):调式机制

第14章 调试机制 支持调试HTML、CSS和JavaScript代码是浏览器或者渲染引擎需要提供的一项非常重要的功能&#xff0c;这里包括两种调试类型&#xff1a;其一是功能&#xff0c;其二是性能。功能调试能够帮助HTML开发者使用单步调试等技术来查找代码中的问题&#xff0c;性能调…

【漏洞复现】零视技术H5S视频平台信息泄漏漏洞

Nx01 产品简介 零视技术(上海)有限公司是以领先的视频技术服务于客户&#xff0c;致力于物联网视频开发简单化&#xff0c;依托于HTML5 WebRTC 等新的技术&#xff0c;实现全平台视频播放简单化。 Nx02 漏洞描述 零视技术(上海)有限公司H5S CONSOLE存在未授权访问漏洞&#xf…

ElasticSearch重建/创建/删除索引操作 - 第501篇

历史文章&#xff08;文章累计500&#xff09; 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 《国内最全的Spring Boot系列之六》 E…

在WSL2中利用gradle构建项目时出现:Could not connect to the Gradle daemon. 的解决方案

最近本人在做基于expo开发的某个APP&#xff0c;由于某种原因&#xff0c;eas云构建连接不上&#xff08;卡在连接谷歌那一步&#xff09;&#xff0c;于是想要利用官方提供的本地构建功能在本地构建一下&#xff0c;结果在wsl这里摔了个跟头&#xff09;&#xff09; eas要求必…

WSL—子系统安装及其相关配置和[诸多报错问题]-修改默认安装位置

一、WSL简介 WSL的全称是Windows Subsystem for Linux。 适用于 Linux 的 Windows 子系统可让开发人员按原样运行 GNU/Linux 环境 - 包括大多数命令行工具、实用工具和应用程序 - 且不会产生传统虚拟机或双启动设置开销。 二、开启WSL功能 系统要求&#xff1a;win10/11 专业…

前端Vue v-for 的使用

目录 ​编辑 简介 使用方式 基本使用 v-for"(item, index)中item和index作用 示例 迭代对象 示例 结果 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&#xff0c;我们往往容易陷入…