前端框架 使用React 开发一个井字棋(2)React.Component组件介绍

2023-10-27

React 是什么?

React 是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库。使用 React 可以将一些简短、独立的代码片段组合成复杂的 UI 界面,这些代码片段被称作“组件”。

React 中拥有多种不同类型的组件,我们先从 React.Component 的子类开始介绍:

class ShoppingList extends React.Component {
  render() {
    return (
      <div className="shopping-list">
        <h1>Shopping List for {this.props.name}</h1>
        <ul>
          <li>Instagram</li>
          <li>WhatsApp</li>
          <li>Oculus</li>
        </ul>
      </div>
    );
  }
}

用法:

<ShoppingList name="Mark" />

等同于:

return React.createElement('div', {className: 'shopping-list'},
  React.createElement('h1', /* ... h1 children ... */),
  React.createElement('ul', /* ... ul children ... */)
);
通过 Props 传递数据
class Board extends React.Component {
	renderSquare(i) {
		return <Square value={i} />;
  	}
}
class Square extends React.Component {
  render() {
    return (
      <button className="square">
        {this.props.value}
      </button>
    );
  }
}

修改后:在渲染结果中,你可以看到每个方格中都有一个数字。

可以通过在 React 组件的构造函数中设置 this.state 来初始化 state。this.state 应该被视为一个组件的私有属性。我们在 this.state 中存储当前每个方格(Square)的值,并且在每次方格被点击的时候改变这个值。

class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null,
    };
  }

  render() {
    return (
      <button className="square" onClick={() => alert('click')}>
        {this.props.value}
      </button>
    );
  }
}

现在,我们来修改一下 Square 组件的 render 方法,这样,每当方格被点击的时候,就可以显示当前 state 的值了:

  • 在 <button> 标签中,把 this.props.value 替换为 this.state.value
  • 将 onClick={…} 事件监听函数替换为 onClick={() => this.setState({value: ‘X’})}。
  • 为了更好的可读性,将 className 和 onClick 的 prop 分两行书写。

修改之后:

class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null,
    };
  }

  render() {
    return (
      <button
        className="square"
        onClick={() => this.setState({value: 'X'})}
      >
        {this.state.value}
      </button>
    );
  }
}
状态提升

为 Board 组件添加构造函数,将 Board 组件的初始状态设置为长度为 9 的空值数组:

class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
    };
  }

  renderSquare(i) {
    return <Square value={this.state.squares[i]} />;
  }
}

接下来,我们要修改一下 Square 的点击事件监听函数。Board 组件当前维护了那些已经被填充了的方格。我们需要想办法让 Square 去更新 Board 的 state。由于 state 对于每个组件来说是私有的,因此我们不能直接通过 Square 来更新 Board 的 state。

相反,从 Board 组件向 Square 组件传递一个函数,当 Square 被点击的时候,这个函数就会被调用。接着,我们将 Board 组件的 renderSquare 方法改写为如下效果:

renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}
      />
    );
}

现在我们从 Board 组件向 Square 组件中传递两个 props 参数:value 和 onClick。onClick prop 是一个 Square 组件点击事件监听函数。接下来,我们需要修改 Square 的代码:

class Square extends React.Component {
  render() {
    return (
      <button
        className="square"
        onClick={() => this.props.onClick()}
      >
        {this.props.value}
      </button>
    );
  }
}

这时候我们点击 Square 的时候,浏览器会报错,因为我们还没有定义 handleClick 方法。我们现在来向 Board 里添加 handleClick 方法:

class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
    };
  }

  handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = 'X';
    this.setState({squares: squares});
  }

  renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}
      />
    );
  }

  render() {
    const status = 'Next player: X';

    return (
      <div>
        <div className="status">{status}</div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}

现在,我们可以通过点击 Square 来填充那些方格,效果与之前相同。但是,当前 state 没有保存在单个的 Square 组件中,而是保存在了 Board 组件中。每当 Board 的 state 发生变化的时候,这些 Square 组件都会重新渲染一次。把所有 Square 的 state 保存在 Board 组件中可以让我们在将来判断出游戏的胜者。

因为 Square 组件不再持有 state,因此每次它们被点击的时候,Square 组件就会从 Board 组件中接收值,并且通知 Board 组件。在 React 术语中,我们把目前的 Square 组件称做“受控组件”。在这种情况下,Board 组件完全控制了 Square 组件。

注意,我们调用了 .slice() 方法创建了 squares 数组的一个副本,而不是直接在现有的数组上进行修改。

为什么不可变性在 React 中非常重要
  • 简化复杂的功能:不可变性使得复杂的特性更容易实现。
  • 跟踪数据的改变:如果直接修改数据,那么就很难跟踪到数据的改变。跟踪数据的改变需要可变对象可以与改变之前的版本进行对比,这样整个对象树都需要被遍历一次。跟踪不可变数据的变化相对来说就容易多了。如果发现对象变成了一个新对象,那么我们就可以说对象发生改变了。
  • 确定在 React 中何时重新渲染:不可变性最主要的优势在于它可以帮助我们在 React 中创建 pure components。我们可以很轻松的确定不可变数据是否发生了改变,从而确定何时对组件进行重新渲染。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

前端框架 使用React 开发一个井字棋(2)React.Component组件介绍 的相关文章

  • 响应式图像 - srcset 和尺寸属性 - 如何正确使用两者:基于设备像素比和基于视口的选择一起?

    到目前为止 我经常读到这个问题 并且它也发生在我自己的项目中 这里介绍一下我到目前为止所发现的关于 srcset 和 size 属性的内容 关于如何使用有两种不同的可能性srcset 属性 来源 w3c http w3c github io
  • 如何将内联 JavaScript 与 Express/Node.js 中动态生成的内容分开?

    对于具有几年 Web 开发经验但没有找到答案的人来说 这是一个有点菜鸟的问题程序员堆栈交换 or Google 我决定在这里问一下 我在用Express网络框架Node js 但这个问题并不特定于任何 Web 框架或编程语言 以下是从数据库
  • 摩卡 - Chai Karma“套件未定义”

    我对 jscript tdd 很陌生 遇到了问题 希望有人能告诉我我在做什么 在浏览器中运行测试 通过 HTML 文件 一切正常 通过节点和业力运行它们我得到以下异常 我想在 node js 主机的 karma 中使用 Mocha 和 Ch
  • 最大宽度调整以适应文本?

    不是最好的标题 但无论如何 我有一个元素max width和一些文字 如果文本长度超过一行所能容纳的长度 我会得到以下结果 My text here hello everyone 换句话说 它占据了完整的最大宽度 但由于单词向下移动 右侧有
  • 在打字稿中导入 json

    我是 typescript 的新手 在我的项目中 我们使用 typescript2 在我的要求之一中 我需要导入 json 文件 所以我创建了 d ts 文件如下 test d ts declare module json const va
  • 如何纠正流警告:解构(缺少注释)

    我正在编写一个小型 React Native 应用程序 并且正在尝试使用 Flow 但我无法在任何地方真正获得有关它的正确教程 我不断收到错误 destructuring Missing annotation 有关 station 这段代码
  • 为 Angular2 中的组件加载多个样式表

    我正在构建一个 angular2 应用程序 当我尝试为同一组件加载多个样式表时 我面临多个问题 这是我正在做的代码 import Component from angular core Component selector my tag t
  • 如何选择具有“A”类但不具有“B”类的 div?

    我有一些 div div class A Target div div class A B NotMyTarget div div class A C NotMyTarget div div class A D NotMyTarget di
  • 调整图像大小并将画布旋转 90 度

    这里有很多关于在 js 上使用画布旋转图像的主题 我阅读了其中的大部分内容 但无法找到解决我的问题的方法 我正在接收任何分辨率的图像 来自上传组件 我将其大小调整为 1024x768 如下所示 var canvas document cre
  • 尝试将数据存储在点击器网站中

    我正在尝试存储一个名为的变量score无论何时刷新 您都会一次又一次地使用它 我不明白的是它的代码是什么 我尝试了一些方法 但似乎都不起作用 这是我的答题器网站 但是当我尝试使用 JavaScript 来存储它时 它不起作用window o
  • 使用 CSS 使一行 div 高度相同

    我有一排必须具有相同高度的 div 但我无法提前知道该高度可能是多少 内容来自外部源 我最初尝试将 div 放置在封闭的 div 中并将它们向左浮动 然后我将它们的高度设置为 100 但这没有明显的效果 通过将封闭 div 的高度设置为固定
  • 将 UMD Javascript 模块导入浏览器

    你好 我正在对 RxJS 进行一些研究 我可以通过在浏览器中引用它来使用该库 如下所示 它使用全局对象命名空间变量 Rx 导入 我可以制作可观察的东西并做所有有趣的事情 当我将 src 更改为指向最新的 UMD 文件时 一切都会崩溃 如下所
  • 有没有办法在 onclick 触发时禁用 iPad/iPhone 上的闪烁/闪烁?

    所以我有一个有 onclick 事件的区域 在常规浏览器上单击时 它不会显示任何视觉变化 但在 iPad iPhone 上单击时 它会闪烁 闪烁 有什么办法可以阻止它在 iPad iPhone 上执行此操作吗 这是一个与我正在做的类似的示例
  • 正则表达式 - 从 markdown 字符串中提取所有标题

    我在用灰质 https www npmjs com package gray matter 以便将文件系统中的 MD 文件解析为字符串 解析器产生的结果是这样的字符串 n Clean er ReactJS Code Conditional
  • 日期出现奇怪的错误,“未捕获非法访问”

    所以我试图找到最新的DateJavascript 可以处理 我把它减少到 9 月 275760 并增加了我开始捕获未捕获的天数illegal access例外new Date 09 24 275760 to new Date 10 13 2
  • Vue 和 Vuex:处理依赖的计算属性

    我的应用程序是一个使用 Vuex 在 Vue 中构建的精简电子表格 关键组件是TableCollection Table and Row The TableCollection有一个包含多个的数组Table对象 每个Table有一个包含多个
  • 使用css bootstrap时如何仅向一列添加右边框?

    我正在尝试使用CSS引导框架 http getbootstrap com css tables在我的项目中 我正在使用带有以下类的表table table bordered table striped 我想删除除第一列之外的所有列的边框 这
  • 在 Javascript 中连接空数组

    我正在浏览一些代码 我想知道这有什么用处 grid push concat row 根据我的理解 它等同于 grid push row 为什么要大惊小怪 连接 你想使用 concat当您需要展平数组并且没有由其他数组组成的数组时 例如 va
  • 在 Shopify 商店中嵌入 Vue 组件

    在产品页面中 我尝试显示自定义 Vue 组件 为简洁起见 该组件根据给定的产品 ID 显示 Firebase 数据库中的一些信息 我最初尝试将其制作为 Shopify 应用程序 以便我可以访问他们的 API 我实现了 OAuth 并且可以检
  • Javascript - 水波纹效果

    我需要 JS 上的脚本 它将以 水波纹 样式更改 images html 抱歉 6MB GIF 文件 http fcuunited ru temp listening2 gif http fcunited ru temp listening

随机推荐

  • SpringMVC使用stringHttpMessageConverter

    SpringMVC使用stringHttpMessageConverter 场景演示 解决方法 场景演示 当使用 ReponseBody注解的时候 我们知道返回值会被转换成 Json格式 然而里面的中文可能会被转换成乱码 如下面代码中的 测
  • 18.一篇文章,从源码深入详解ThreadLocal内存泄漏问题

    1 造成内存泄漏的原因 threadLocal是为了解决对象不能被多线程共享访问的问题 通过threadLocal set方法将对象实例保存在每个线程自己所拥有的threadLocalMap中 这样每个线程使用自己的对象实例 彼此不会影响达
  • 【笔记总结】C++面向对象三大特征(四大特征)

    C 面向对象的三大特征 四大特征 三大特征 封装 继承 多态 四大特征 抽象 封装 继承 多态 一 类和对象 什么是类 什么是对象 类和对象的区别 类是数据类型 是具有相同属性和服务的一组对象的集合 对一类对象的抽象就是类 对象即观察研究对
  • 转换vmware的vmdk格式为qcow2格式

    一 系统环境 操作系统 Win11 虚机系统 VMware Workstation 16 Pro 16 2 3 build 19376536 转换工具 qemu 8 0 2 二 下载安装qemu模拟器 查看qemu版本 Download Q
  • Python强大的内置模块collections

    1 模块说明 collections 是 Python 的一个内置模块 所谓内置模块的意思是指 Python 内部封装好的模块 无需安装即可直接使用 collections 包含了一些特殊的容器 针对 Python 内置的容器 例如 lis
  • C语言和指针数组有关的一些题目

    文章目录 一 一维数组的大小 二 字符数组 2 1 2 2 2 3 三 二维数组 四 指针笔试题 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 一 一维数组的大小 数组名的意义 1 sizeof 数组名 这里的数组名表示整
  • matlab数据过大,无法正常保存

    matlab存储数据时 存储不进mat文件 如下存在三个为1KB的文件 便是存储不成功的 这是因为对于过大的文件 大于2GB的变量 需要使用MAT file版本7 3或更高版本 解决方法如下 进入matlab 主页 点击 预设 按钮 选择
  • el-input和el-select的框的宽度设置成一致的。

    其实在el select的底层其实就是el input 只要将el select加一个属性 就是将其width设置为100 原因是什么呢 有待研究
  • BTC-匿名性

    Bitcoin and anonymity 比特币中不要求用真名 可以用公钥产生的地址 可以产生任意多的地址 用不同的地址干不同的事情 用的是化名 也被叫做pseudonymity 一般来说 匿名性多与隐私保护相关 但实际上 比特币中的匿名
  • DynamicDet: A Unified Dynamic Architecture for Object Detection 一个目标检测器的通用动态架构

    目录 检测代码 本文分享 CVPR 2023 论文 DynamicDet A Unified Dynamic Architecture for Object Detection 北京大学王选计算机研究所王勇涛团队所提出的一个目标检测器的通用
  • matlab练习程序(对应点集配准的四元数法)

    这个算是ICP算法中的一个关键步骤 单独拿出来看一下 算法流程如下 1 首先得到同名点集P和X 2 计算P和X的均值up和ux 3 由P和X构造协方差矩阵sigma 4 由协方差矩阵sigma构造4 4对称矩阵Q 5 计算Q的特征值与特征向
  • 记录--手把手教你Vue+ECharts+高德地图API实现天气预报数据可视化

    这里给大家分享我在网上总结出来的一些知识 希望对大家有所帮助 前言 所谓数据可视化 我们可以理解为从宏观角度来看一眼就能看出来整个数据的占比 走向 对于数据可视化 很多互联网公司是很看重这一块的 包括大厂 就比如阿里的淘宝 双十一的时候往往
  • 【小沐学NLP】关联规则分析Apriori算法(Mlxtend库,Python)

    文章目录 1 简介 2 Mlxtend库 2 1 安装 2 2 功能 2 2 1 User Guide 2 2 2 User Guide data 2 2 3 User Guide frequent patterns 2 3 入门示例 3
  • 随机变量序列的两种收敛性

    随机变量序列的收敛性有多种 其中常用的是两种 依概率收敛和依分布收敛 大数定律涉及的是一种依概率收敛 中心极限定理涉及的是依分布收敛 1 依概率收敛 为什么要研究随机变量序列的收敛性 依概率收敛的定义 依概率收敛于常数的四则运算 2 依分布
  • 简单HTML的使用

    1 html的简介 什么是html HyperText Markup Language 超文本标记语言 网页语言 超文本 超出文本的范畴 使用html可以轻松实现这样的操作 标记 html所有的操作都是通过标记实现的 标记就是标签 lt 标
  • 如何判断是PC端还是移动端

    app vue 中 mounted if this browser mobile this browser android this browser ios document body clientWidth lt 787 判断是否是移动端
  • 任务调度系统(定时任务)

    1 运行流程 Cron表达式 设置触发规则 调度器 调度器本身就是一个线程 并且一定是单例的 如果不是单例 会出现多指挥官 任务乱套问题 存储任务位置 默认保存在内存中 RAMJobStore 出现重启后找不到任务问问题 所以可以在配置文件
  • Java语言学习基础

    文章目录 Java语言学习基础 01 计算机基础知识 01 01 计算机概述 01 02 硬件 01 03 软件 01 04 人机交互 01 05 计算机语言 01 06 常见的DOS命令 01 07 Java语言跨平台原理 01 08 J
  • 史上最全的CSP-J/S 第一轮知识点

    CSP J S 第一轮知识点选讲 NOIP 全国青少年信息学奥林匹克竞赛 于2019年取消 取而代之的是由 CCF 推出的非专业级软件能力认证 也就是现在的 CSP J S 作为一名于2019年1月入 OI 的蒟蒻 OIer 没能参加 NO
  • 前端框架 使用React 开发一个井字棋(2)React.Component组件介绍

    React 是什么 React 是一个声明式 高效且灵活的用于构建用户界面的 JavaScript 库 使用 React 可以将一些简短 独立的代码片段组合成复杂的 UI 界面 这些代码片段被称作 组件 React 中拥有多种不同类型的组件