React-基础语法学习

1、教程:井字棋游戏

本教程将引导你逐步实现一个简单的井字棋游戏,并且不需要你对 React 有任何了解。在此过程中你会学习到一些编写 React 程序的基本知识,完全理解它们可以让你对 React 有比较深入的理解。

1.1、教程分成以下几个部分:

配置是一些准备工作。

概览介绍了 React 的 基础知识:组件、props 和 state。

完成游戏介绍了 React 开发中 最常用的技术

添加时间旅行可以让你更深入地了解 React 的独特优势。

1.2、实现的是什么程序? 

本教程将使用 React 实现一个交互式的井字棋游戏。你可以在下面预览最终成果:

App.js

import { useState } from 'react';

function Square({ value, onSquareClick }) {
  return (
    <button className="square" onClick={onSquareClick}>
      {value}
    </button>
  );
}

function Board({ xIsNext, squares, onPlay }) {
  function handleClick(i) {
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    const nextSquares = squares.slice();
    if (xIsNext) {
      nextSquares[i] = 'X';
    } else {
      nextSquares[i] = 'O';
    }
    onPlay(nextSquares);
  }

  const winner = calculateWinner(squares);
  let status;
  if (winner) {
    status = 'Winner: ' + winner;
  } else {
    status = 'Next player: ' + (xIsNext ? 'X' : 'O');
  }

  return (
    <>
      <div className="status">{status}</div>
      <div className="board-row">
        <Square value={squares[0]} onSquareClick={() => handleClick(0)} />
        <Square value={squares[1]} onSquareClick={() => handleClick(1)} />
        <Square value={squares[2]} onSquareClick={() => handleClick(2)} />
      </div>
      <div className="board-row">
        <Square value={squares[3]} onSquareClick={() => handleClick(3)} />
        <Square value={squares[4]} onSquareClick={() => handleClick(4)} />
        <Square value={squares[5]} onSquareClick={() => handleClick(5)} />
      </div>
      <div className="board-row">
        <Square value={squares[6]} onSquareClick={() => handleClick(6)} />
        <Square value={squares[7]} onSquareClick={() => handleClick(7)} />
        <Square value={squares[8]} onSquareClick={() => handleClick(8)} />
      </div>
    </>
  );
}

export default function Game() {
  const [history, setHistory] = useState([Array(9).fill(null)]);
  const [currentMove, setCurrentMove] = useState(0);
  const xIsNext = currentMove % 2 === 0;
  const currentSquares = history[currentMove];

  function handlePlay(nextSquares) {
    const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];
    setHistory(nextHistory);
    setCurrentMove(nextHistory.length - 1);
  }

  function jumpTo(nextMove) {
    setCurrentMove(nextMove);
  }

  const moves = history.map((squares, move) => {
    let description;
    if (move > 0) {
      description = 'Go to move #' + move;
    } else {
      description = 'Go to game start';
    }
    return (
      <li key={move}>
        <button onClick={() => jumpTo(move)}>{description}</button>
      </li>
    );
  });

  return (
    <div className="game">
      <div className="game-board">
        <Board xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} />
      </div>
      <div className="game-info">
        <ol>{moves}</ol>
      </div>
    </div>
  );
}

function calculateWinner(squares) {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}

如果你还不是很明白上面的代码,不用担心!本教程的目的就是帮你理解 React 及其语法。

我们建议你在继续本教程之前,先看看上面的井字棋游戏。我们会注意到的一项功能是,棋盘右侧有一个编号列表,它记录了游戏中落子的历史,并随着游戏的进行而更新。

体验完游戏以后,继续阅读本教程吧!我们将从一个更简单的模板开始。下一步将介绍相关配置,以便于你着手实现这个游戏。

export default function Square() {
  return <button className="square">X</button>;
}

注意

如果你想要使用本地开发环境来学习这个教程,需要按照下面的流程进行:

安装 Node.js

在之前打开的 CodeSandbox 选项卡中,按左上角的按钮打开菜单,然后选择 Download Sandbox,将代码压缩包下载到本地。下载链接https://codesandbox.io/p/sandbox/react-dev-q2z497?file=%2Fsrc%2FApp.js%3A19%2C13&utm_medium=sandpack

将压缩包解压,打开终端并使用 cd 命令切换到你解压后的目录。

使用 npm install 安装依赖。

运行 npm start 启动本地服务器,按照提示在浏览器中查看运行效果。

1.3、概览

完成配置以后,我们先来大致了解一下 React 吧!看一下刚刚的代码 ,在 CodeSandbox 中,你将看到三个主要的部分:

Files 部分列出了一些文件:App.jsindex.jsstyles.css 和 public 文件夹。

code editor 部分可以看到你所选中文件的源码。

browser 部分可以预览代码的实时结果。

App.js 文件里面的内容应该是这样的:

export default function Square() {
  return <button className="square">X</button>;
}

browser 部分应该会像下面这样在方块里面显示一个 X:

现在,让我们仔细研究一下这些文件吧。

1.4、App.js 

App.js 的代码创建了一个 组件。在 React 中,组件是一段可重用代码,它通常作为 UI 界面的一部分。组件用于渲染、管理和更新应用中的 UI 元素。让我们逐行查看这段代码,看看发生了什么:

export default function Square() {
  return <button className="square">X</button>;
}

第一行定义了一个名为 Square 的函数。JavaScript 的 export 关键字使此函数可以在此文件之外访问。default 关键字表明它是文件中的主要函数。

export default function Square() {
  return <button className="square">X</button>;
}

第二行返回一个按钮。JavaScript 的 return 关键字意味着后面的内容都作为值返回给函数的调用者。<button> 是一个 JSX 元素。JSX 元素是 JavaScript 代码和 HTML 标签的组合,用于描述要显示的内容。className="square" 是一个 button 属性,它决定 CSS 如何设置按钮的样式。X 是按钮内显示的文本,</button> 闭合 JSX 元素以表示不应将任何后续内容放置在按钮内。

1.5、styles.css 

单击 CodeSandbox 中的 styles.css 文件。该文件定义了 React 应用的样式。前两个 CSS 选择器*body)定义了应用大部分的样式,而 .square 选择器定义了 className 属性设置为 square 的组件的样式。这与 App.js 文件中的 Square 组件中的按钮是相匹配的。

1.6、index.js 

单击 CodeSandbox 中的 index.js 的文件。在本教程中我们不会编辑此文件,但它是 App.js 文件中创建的组件与 Web 浏览器之间的桥梁。

import React, { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./styles.css";

import App from "./App";

const root = createRoot(document.getElementById("root"));
root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

第 1-5 行将所有必要的部分组合在一起:

React

React 与 Web 浏览器对话的库(React DOM)

组件的样式

App.js 里面创建的组件

其他文件将它们组合在一起,并将最终成果注入 public 文件夹里面的 index.html 中。

1.7、构建棋盘 

让我们回到 App.js。接下来我们将专注于这个文件。目前棋盘只有一个方块,但你需要九个!如果你只是想着复制粘贴来制作两个像这样的方块:

export default function Square() {
  return <button className="square">X</button><button className="square">X</button>;
}

你将会得到如下错误:

/src/App.js: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX Fragment <>...</>?

React 组件必须返回单个 JSX 元素,不能像两个按钮那样返回多个相邻的 JSX 元素。要解决此问题,可以使用 Fragment(<></>)包裹多个相邻的 JSX 元素,如下所示:

export default function Square() {
  return (
    <>
      <button className="square">X</button>
      <button className="square">X</button>
    </>
  );
}

现在你应该可以看见:

非常棒!现在你只需要通过复制粘贴来添加九个方块,然后……

但事与愿违的是这些方块并没有排列成网格,而是都在一条线上。要解决此问题,需要使用 div 将方块分到每一行中并添加一些 CSS 样式。当你这样做的时候,需要给每个方块一个数字,以确保你知道每个方块的位置。

App.js 文件中,Square 组件看起来像这样:

export default function Square() {
  return (
    <>
      <div className="board-row">
        <button className="square">1</button>
        <button className="square">2</button>
        <button className="square">3</button>
      </div>
      <div className="board-row">
        <button className="square">4</button>
        <button className="square">5</button>
        <button className="square">6</button>
      </div>
      <div className="board-row">
        <button className="square">7</button>
        <button className="square">8</button>
        <button className="square">9</button>
      </div>
    </>
  );
}

借助 styles.css 中定义的 board-row 样式,我们将组件分到每一行的 div 中。最终完成了井字棋棋盘:

但是现在有个问题,名为 Square 的组件实际上不再是方块了。让我们通过将名称更改为 Board 来解决这个问题:

export default function Board() {
  //...
}

此时你的代码应如下所示:App.js

export default function Board() {
  return (
    <>
      <div className="board-row">
        <button className="square">1</button>
        <button className="square">2</button>
        <button className="square">3</button>
      </div>
      <div className="board-row">
        <button className="square">4</button>
        <button className="square">5</button>
        <button className="square">6</button>
      </div>
      <div className="board-row">
        <button className="square">7</button>
        <button className="square">8</button>
        <button className="square">9</button>
      </div>
    </>
  );
}

1.8、通过 props 传递数据 

接下来,当用户单击方块时,我们要将方块的值从空更改为“X”。根据目前构建的棋盘,你需要复制并粘贴九次更新方块的代码(每个方块都需要一次)!但是,React 的组件架构可以创建可重用的组件,以避免混乱、重复的代码。

首先,要将定义第一个方块(<button className="square">1</button>)的这行代码从 Board 组件复制到新的 Square 组件中:

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

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

相关文章

计算机视觉动作识别——YOWO用于实时时空动作定位与识别的算法解析

摘要 时空动作定位要求将两种信息源整合到设计的架构中&#xff1a;(1) 来自先前帧的时间信息和(2) 来自关键帧的空间信息。当前的最先进方法通常使用单独的网络提取这些信息&#xff0c;并使用额外的机制进行融合以获得检测结果。YOWO是一个用于视频流中实时时空动作定位的统…

宏集eX700M系列HMI实现港口设备数据上云

前言 随着港口设备信息化技术的快速发展&#xff0c;越来越多的企业想要把现场设备数据上传到云平台&#xff0c;进而实现关键数据的远程监控和分析处理。在此背景下&#xff0c;国内某信息化公司想要将港口设备数据通过MQTT上传到该公司自研IOT平台&#xff0c;实现数据上云&…

vue-treeselect 的基本使用

vue-treeselect 的基本使用 1. 效果展示2. 安装 插件3. 引入组件4. 代码 1. 效果展示 2. 安装 插件 vue-treeselect是一个树形的下拉菜单&#xff0c;至于到底有多少节点那就要看你的数据源有多少层了&#xff0c;挺方便的。下面这个这个不用多说吧&#xff0c;下载依赖 npm in…

中兴通讯AI全场景终端新品 赋能行业数智化升级发布 (2)

2024年4月11日&#xff0c;南京&#xff0c;在2024年中兴通讯云网生态峰会召开之际&#xff0c;中兴行业终端合作伙伴大会暨春季新品发布会也同期举行。本次大会主题为“强基拓新&#xff0c;价值创造”&#xff0c;中兴行业终端持续践行合作伙伴优先、深度定制更安全更高效的解…

揭秘ebay、亚马逊测评系统:从稳定环境搭建到防关联技术

在亚马逊、ebay平台上进行自养号测评、L ka等活动&#xff0c;首要问题是确保环境的安全性和稳定性。一个稳定的环境是进行测评的基础&#xff0c;如果无法解决安全性问题&#xff0c;那么从事这些项目就不值得。我们在环境技术研发领域已经有8年的经验&#xff0c;在早期测试了…

连连看游戏页面网站源码,直接使用

可以上传自己喜欢的图片 游戏页面 通关页面 源码免费下载地址抄笔记 (chaobiji.cn)

信号分解 | VMD(变分模态分解)-Matlab

分解效果 VMD(变分模态分解) 变分模态分解(Variational Mode Decomposition,VMD)是一种信号分解方法,用于将非平稳信号分解为一组模态函数。VMD是一种自适应的数据驱动方法,可以有效地处理具有非线性和非平稳特性的信号。 VMD的基本思想是通过迭代优化过程,将原始信号分…

4.16学习总结

MySQL数据库学习(一) 一.MySQL数据库的基本知识 (一).数据库 概念&#xff1a;数据仓库,软件,安装在操作系统之上 作用&#xff1a;存储数据&#xff0c;管理数据 (二).数据库的分类 关系型数据库&#xff1a;SQL&#xff08;Structured Query Language&#xff09; MySQL…

创建k8s deploy yaml文件的imagePullSecrets语句

镜像仓库是harbor kubectl create secret docker-registry key --docker-server192.168.0.190 --docker-usernameadmin --docker-passwordHarbor12345

Fluke ADPT连接器(隔离版)----发布1

代替手工记录、记录后在整理的麻烦&#xff0c;轻点鼠标&#xff08;单次采集、自动时间间隔采集自由选择&#xff09;即可完成&#xff0c;测试数据导出图片、导出数据到EXCEL文件随意选择&#xff1b; 所需设备&#xff1a; 1、Fluke ADPT连接器&#xff1b;内附链接 主要…

docker网路和主机通讯问题

#注 1&#xff0c;安装docker和启动容器服务的时候如果防火墙处于开启状态&#xff0c;那么重启docker里面的容器的时候必须开启防火墙&#xff0c;否则会出现iptable错误&#xff1b; 2&#xff0c;linux开启防火墙会导致主机和docker网络之间单向通讯&#xff0c;主机可以访…

Ubuntu 部署ChatGLM3大语言模型

Ubuntu 部署ChatGLM3大语言模型 ChatGLM3 是智谱AI和清华大学 KEG 实验室联合发布的对话预训练模型。 源码&#xff1a;https://github.com/THUDM/ChatGLM3 部署步骤 1.服务器配置 Ubuntu 20.04 8核(vCPU) 32GiB 5Mbps GPU NVIDIA T4 16GB 硬盘 100GiB CUDA 版本 12.2.2/…

专业143总分428学硕第一东南大学920专业基础综合考研经验电子信息与通信工程,海洋工程,电路系统,鲁汶,真题,大纲,参考书。

24考研基本已经尘埃落定&#xff0c;总归要为回忆留下点什么。回想起这一年的备考之路&#xff0c;至今仍觉得时间过得很快&#xff0c;有些感到恍惚&#xff0c;似乎不能接受。但是仔细思考一下&#xff0c;这一年经历了很多&#xff0c;走过很多弯路也取得一些阶段性的小成功…

Hive-Sql复杂面试题

参考链接&#xff1a;hive sql面试题及答案 - 知乎 有哪些好的题目都可以给我哦 我来汇总到一起 1、编写sql实现每个用户截止到每月为止的最大单月访问次数和累计到该月的总访问次数 数据&#xff1a; userid,month,visits A,2015-01,5 A,2015-01,15 B,2015-01,5 A,2015-01,…

独角数卡发卡系统源码hyper模版首页产品列表添加库存数量显示的方法

默认的独角数卡hyper模版商品列表只显示标题和价格&#xff0c;没有显示库存数量 如图&#xff1a; 对于买家来说&#xff0c;无法通过首页快捷的知道某事产品的库存数量 故此在此列出显示库存数量的修改方法。 首先找到根目录下文件/resources/views/hyper/static_pages/ho…

Servlet-Filter实现反爬虫

以前用DotNetCore实现过反爬虫功能。在tomcat里面可以利用Servlet的Filter类实现请求的控制来达到反爬虫功能&#xff0c;进而增强JRT的web安全。 实现黑名单过滤器&#xff0c;对在黑名单列表的IP的所有请求都跳转到警告页面&#xff0c;业务各种请求自行定义加入黑名单 /* …

Vanna-ai 大模型开源项目 基于RAG的TextToSql框架 安装和使用教程

github项目地址&#xff1a;vanna-ai/vanna: &#x1f916; 与 SQL 数据库聊天&#x1f4ca;。通过 LLMs使用RAG进行准确的TextToSQL的生成工作 &#x1f504; 。 Vanna 是 MIT 许可的开源 Python RAG&#xff08;检索增强生成&#xff09;框架&#xff0c;用于 SQL 生成和相关…

逻辑回归模型-逻辑回归算法原理-逻辑回归代码与实现-笔记整合

通过一段时间的学习&#xff0c;总算把逻辑回归模型弄清楚了 《老饼讲解-机器学习》www.bbbdata.com中是讲得最清晰的&#xff0c;结合其它资料&#xff0c;整理一个完整的笔记如下&#xff0c;希望能帮助像我这样入门的新人&#xff0c;快速理解逻辑回归算法原理和逻辑回归实…

【解决去除springboot-内嵌tomcat的异常信息显示】去掉版本号和异常信息

调用这个&#xff0c;能复现tomcat的报错 http://localhost:8182/defaultroot/DownloadServlet?modeType2&pathhtml&FileName…\login.jsp&name123&fiewviewdownload2&cdinline&downloadAll2 springboot项目如何隐藏&#xff1f; springboot内嵌了to…

人类连接的桥梁:探索Facebook如何连接世界

随着技术的发展和全球化的进程&#xff0c;我们的世界正在变得越来越紧密相连。在这个过程中&#xff0c;社交媒体平台扮演了一个至关重要的角色&#xff0c;为人们提供了一个跨越国界、文化和语言的交流平台。其中&#xff0c;Facebook作为全球最大的社交媒体平台&#xff0c;…