React学习笔记:组件

news2024/9/25 9:33:57

组件

将页面按照界面功能进行拆分,每一块界面都拥有自己的独立逻辑(组件),这样可以提高项目代码的可维护性和复用性。
在这里插入图片描述
如上图所示将这个卡片分为三个组件,那么当需要添加一个这样的卡片时,就可以复用这些组件,只需要稍稍改变一下这些组件的文字和一些参数就好了,大大提高了代码的复用性,并且若后期维护需要改变样式那么只需要改变对应组件的样式,所有的卡片的样式都会改变,大大提高了项目的可维护性。

类组件

使用class语法创建的组件就是类组件

  • 类名首字母必需大写。 类中的构造器不是必须要写的,要对实例进行一些初始化的操作,如添加指定属性时才写。
  • 必须继承React.Component父类
  • 必需有render函数,返回 UI 结构,无渲染可返回 null
  • 如果A类继承了B类,且A类中写了构造器,那么A类构造器中的super是必须要调用的。
  • 类中所定义的方法,都放在了类的原型对象上,供实例去使用。
<body>
  <div id="root"></div>
  <script type="text/javascript" src="./js/react.development.js"></script>
  <script type="text/javascript" src="./js/react-dom.development.js"></script>
  <script type="text/javascript" src="./js/babel.min.js"></script>
  <script type="text/babel">
    // 类组件
    class Head extends React.Component {
      render() {
        return (
          <div>
            这是组件
          </div>
        )
      }
    }
    // 根组件
    class App extends React.Component {
      render() {
        return (
          <div>
            <Head />
            <div style={{ height: 200, backgroundColor: 'red' }}>body</div>
          </div>
        );
      }
    }
    // 渲染虚拟dom
    ReactDOM.render(<App />, document.getElementById('root'));
  </script>
</body>

注意

  • render 是放在 MyComponent 的原型对象上,供实例使用。
  • render 中的 this 是 MyComponent 的实例对象 <=> MyComponent组件实例对象。

执行了 ReactDOM.render(<MyComponent/>....... 之后,发生了什么?

  1. React解析组件标签,找到了MyComponent组件。
  2. 发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法。
  3. 将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。

上面的这种把所有组件写在一个文件中会导致后期维护很麻烦,所以我们可以把每个组件单独的写在一个文件中,需要使用哪个组件就引入哪个组件。

状态

根据组件是否有状态可以将组件分为有状态组件和无状态组件。

  • 无状态组件:组件本身不定义状态,没有组件生命周期,只负责 UI 渲染。
  • 有状态组件:组件本身有独立数据,拥有组件生命周期,存在交互行为。

对比两种组件
无状态组件由于没有维护状态只做渲染,性能较好。有状态组件提供数据和生命周期,能力更强。

state

state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合),组件被称为"状态机"。使用state的时候通过this去访问即可,例如:this.state.xxx。下面的 Head 组件是有状态组件,Body 是无状态组件

<body>
  <div id="root"></div>
  <script type="text/javascript" src="./js/react.development.js"></script>
  <script type="text/javascript" src="./js/react-dom.development.js"></script>
  <script type="text/javascript" src="./js/babel.min.js"></script>
  <script type="text/babel">
    // 类组件
    class Head extends React.Component {
      state = {
        name: '孤城浪人',
        age: 18
      }
      render() {
        return (
          <div>
            姓名:{this.state.name}<br />
            年龄:{this.state.age}
          </div>
        )
      }
    }
    class Body extends React.Component {
      render() {
        return (
          <div>
            body
          </div>
        )
      }
    }
    // 根组件
    class App extends React.Component {
      render() {
        return (
          <div>
            <Head />
            <div style={{ height: 200, backgroundColor: 'red' }}>body</div>
          </div>
        );
      }
    }
    // 渲染虚拟dom
    ReactDOM.render(<App />, document.getElementById('root'));
  </script>
</body>

setState

状态(state)不可直接更改,状态必须通过 setState 方法进行更新,且更新是一种浅合并(只会合并相同 key 的值),不是替换。

setState 是“异步”的,多次 setState 会合并。
setState 是“异步”的,合并更新调用 setState 时,将要更新的状态对象,放到一个更新队列中暂存起来(没有立即更新)。如果多次调用 setState 更新状态,状态会进行合并,后面覆盖前面等到所有的操作都执行完毕,React 会拿到最终的状态,然后触发组件更新。这么做的目的是为了提升渲染性能

  • setState 接收一个对象
<body>
  <div id="root"></div>
  <script type="text/javascript" src="./js/react.development.js"></script>
  <script type="text/javascript" src="./js/react-dom.development.js"></script>
  <script type="text/javascript" src="./js/babel.min.js"></script>
  <script type="text/babel">
    // 类组件
    // 根组件
    class App extends React.Component {
      state = {
        count: 0
      }
      addCount = () => {
        this.setState({ count: this.state.count + 2 });
        this.setState({ count: this.state.count + 1 });
      }
      render() {
        return (
          <div>
            <div>
              {this.state.count}
            </div>
            <button onClick={this.addCount}>add</button>
          </div>
        );
      }
    }
    // 渲染虚拟dom
    ReactDOM.render(<App />, document.getElementById('root'));
  </script>
</body>

上面的例子中,点击按钮每次加 1,并不是 2,也不是 3 可以证明后面的 setState 覆盖了前边的。

  • setState 接收函数
    如果传给 setState 的是一个函数的话,那么这个函数可以拿到当前的 state。如果传了两个函数的话,那么在数据更新完后会执行第二个参数函数。
<body>
  <div id="root"></div>
  <script type="text/javascript" src="./js/react.development.js"></script>
  <script type="text/javascript" src="./js/react-dom.development.js"></script>
  <script type="text/javascript" src="./js/babel.min.js"></script>
  <script type="text/babel">
    // 类组件
    // 根组件
    class App extends React.Component {
      state = {
        count: 0
      }
      addCount = () => {
        this.setState(preState => preState.count++, () => console.log(this.state));
      }
      render() {
        return (
          <div>
            <div>
              {this.state.count}
            </div>
            <button onClick={this.addCount}>add</button>
          </div>
        );
      }
    }
    // 渲染虚拟dom
    ReactDOM.render(<App />, document.getElementById('root'));
  </script>
</body>

受控组件与非受控组件

  • 非受控组件:没有通过 state 控制的表单元素,它自己控制自身的值
  • 受控组件:表单元素的值被 React 中 state 控制,这个表单元素就是受控组件。

下面的例子中 Head 组件中 input 的值由 state.name 决定,所以它是受控组件,而 Body 组件中 input 的值由它自己决定,所以它是非受控组件。

<body>
  <div id="root"></div>
  <script type="text/javascript" src="./js/react.development.js"></script>
  <script type="text/javascript" src="./js/react-dom.development.js"></script>
  <script type="text/javascript" src="./js/babel.min.js"></script>
  <script type="text/babel">
    // 类组件
    class Head extends React.Component {
      state = {
        name: '孤城浪人',
        age: 18
      }
      changeName = () => {
        this.setState({ name: '孤城' });
      }
      render() {
        return (
          <div>
            姓名:{this.state.name}<br />
            年龄:{this.state.age}<br />
            <input type="text" value={this.state.name} />
            <button onClick={this.changeName}>changeName</button>
          </div>
        )
      }
    }
    class Body extends React.Component {
      render() {
        return (
          <div>
            <input type="text" />
          </div>
        )
      }
    }
    // 根组件
    class App extends React.Component {
      render() {
        return (
          <div>
            <Head />
          </div>
        );
      }
    }
    // 渲染虚拟dom
    ReactDOM.render(<App />, document.getElementById('root'));
  </script>
</body>

函数组件

函数组件就跟他的名字一样是一个函数,如下例子,必须要返回 UI 结构。

<body>
  <div id="root"></div>
  <script type="text/javascript" src="./js/react.development.js"></script>
  <script type="text/javascript" src="./js/react-dom.development.js"></script>
  <script type="text/javascript" src="./js/babel.min.js"></script>
  <script type="text/babel">
    // 渲染虚拟dom
    function App() {
      return (
        <div>
          我是 APP 组件
        </div>
      )
    }
    ReactDOM.render(<App />, document.getElementById('root'));
  </script>
</body>

状态

在 16.8 版本以前函数组件是没有状态的,16.8 版本推出Hooks API就使得函数组件和类组件的功能性一致了,既有状态,也有了生命周期方法。这里只简单说一下 useState 和 useEffect 两个 API。

  • useState:使用方法如下,让函数组件也有状态,注意: useState 不可以用 if…else
  • useEffect:使用方法如下,当第二个参数为[]时会在组件挂载时就会重新调用第一个参数函数,若第二个参数为[name],那么每次 name 变化时就会重新调用第一个参数函数。
function App() {
      const [ name, setName ] = useState();
      useEffect(() => {
        setName('孤城浪人');
      }, [])
      return (
        <div>
          姓名:{name}
        </div>
      )
    }

更改状态就调用就调用 useState 方法返回的第二个参数,他是一个函数,将新值作为参数调用就行了。

受控组件

因为函数组件有了状态,那么这里受控组件就和类组件的受控与非受控组件非常相似了。

我是孤城浪人,一名正在前端路上摸爬滚打的菜鸟,欢迎你的关注。

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

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

相关文章

【Java进阶篇】第八章 反射与注解

文章目录一、反射机制概述1、作用2、相关类二、反射1、获取Class的三种方式2、通过反射机制实例化对象3、forName方法的另一个应用4、获取类路径下文件的绝对路径5、资源绑定器ResourceBundle6、类加载器三、反射与反编译1、获取Field2、反编译Field3、通过反射机制访问对象的属…

Akka 学习(七)Actor的生命周期

在Actor的生命周期中会调用几个方法&#xff0c;我们在需要时可以重写这些方法。 ● prestart()&#xff1a;在构造函数之后调用。 ● postStop()&#xff1a;在重启之前调用。 ● preRestart(reason, message)&#xff1a;默认情况下会调用postStop()。 ● postRestart()&…

D/A转换器

性能指标&#xff1a;转换精度&#xff0c;转换速度 相互之间是矛盾的&#xff0c;精度越高&#xff0c;相比而言速度就会慢一些 权电阻网络D/A转换器 阻值的选取是按照二进制的位权来选择的&#xff0c;所以我们看到了这个结构&#xff0c;和我们刚才分析的是一致的 权电阻网…

基于花授粉算法优化的lssvm回归预测-附代码

基于花授粉算法优化的lssvm回归预测 - 附代码 文章目录基于花授粉算法优化的lssvm回归预测 - 附代码1.数据集2.lssvm模型3.基于花授粉算法优化的LSSVM4.测试结果5.Matlab代码摘要&#xff1a;为了提高最小二乘支持向量机&#xff08;lssvm&#xff09;的回归预测准确率&#xf…

c++11 std::thread和mutex用法

c11 std::thread和mutex用法thread和mutex用法thread简单示例thread构造函数梳理thread关键成员函数mutex使用thread和mutex用法 本文对c 11中的std::thread 和 mutex作简要的使用说明 thread简单示例 #include <iostream> #include <string> #include <thre…

mysql性能监控

一.使用show profile查询剖析工具&#xff0c;查看mysql语句执行时间&#xff1a; 官网&#xff1a;https://dev.mysql.com/doc/refman/8.0/en/show-profile.html mysql -uroot -p //进入数据库服务器 use 数据库名 //进入数据库 set profiling1; //开启profiling参数 select…

Python基础(十二):字典的详细讲解

文章目录 字典的详细讲解 一、字典的应用场景 二、创建字典的语法

具身智能综述和应用(Embodied AI)

什么是具身智能&#xff1f; 目前人工智能的进展&#xff0c;在诸多数据源和数据集&#xff08;Youtube、Flickr、Facebook&#xff09;、机器计算能力&#xff08;CPU、GPU、TPU&#xff09;的加持下&#xff0c;已经在CV、NLP上取得了许多任务&#xff08;如目标检测、语义分…

Python学习----闭包和装饰器

情景&#xff1a; 当我们调用函数的时候&#xff0c;函数调用完成之后&#xff0c;函数内定义的变量都会被销毁&#xff0c;但是我们有时候需要保存函数内的这个变量&#xff0c;每次在这个变量的基础上完成一系列的操作&#xff0c;比如&#xff1a;每次在这个变量的基础上和其…

【全网惟一面向软件测试人员的Python基础教程】- 学Python之前要搞懂的道理

全网惟一面向软件测试人员的Python基础教程 起点&#xff1a;《python软件测试实战宝典》介绍 第一章 为什么软件测试人员要学习Python 第二章 学Python之前要搞懂的道理 文章目录全网惟一面向软件测试人员的Python基础教程计算机的本质是什么&#xff1f;什么是编程呢&#x…

Java泛型的使用和原理

文章目录泛型-概述基础使用泛型类的使用泛型类派生子类泛型接口泛型方法类型通配符类型通配符上限类型通配符下限常用泛型标识符类型擦除使用注意泛型与数组泛型和反射其他泛型-概述 Java 泛型&#xff08;generics&#xff09;是 JDK 5 中引入的一个新特性&#xff0c;泛型提…

第十四届蓝桥杯集训——JavaC组第八篇——进制转换

第十四届蓝桥杯集训——JavaC组第八篇——进制转换 目录 第十四届蓝桥杯集训——JavaC组第八篇——进制转换 短除法 十进制转二进制示例&#xff1a; 十进制转换二进制 十进制转换八进制 十进制转换十六进制 二进制转十进制 八进制转十进制 十六进制转十进制 进制转换…

【✨十五天搞定电工基础】半导体器件

本章要求1. 理解PN结的单向导电性&#xff0c;三极管的电流分配和电流放大作用 2. 了解二极管、稳压管和三极管的基本构造、工作原理和特性曲线&#xff0c;理解主要参数的意义 3. 会分析含有二极管的电路 目录 一、半导体基础知识 1、本征半导体的导电机理 2、杂质半导体 …

部分核心技术(持续更新)

文章目录1.Schedule&#xff08;定时任务&#xff09;2.高并发线程安全的解决方案2.1为什么不适用同步锁&#xff08;Synchronized&#xff09;&#xff1f;2.2 Redis的分布式锁setnx2.3 redisson分布式锁&#xff08;看门狗机制&#xff09;2.3.1 Redis的分布式锁setnx产生的问…

保姆级入门nest笔记

使用 NEXT 搭建后台服务接口 https://docs.nestjs.com/ # 准备工作 安装 node 全局安装 nest npm i -给nestjs/cli nest --version # 创建项目 创建项目next new 启动项目npm run start 或 npm run start:dev 访问接口 localhost:3000 获取命令解释 next g -h # 快速创建…

Pixracer接线图 及电调调参 BLheliSuite

Pixracer接线指南 pixracer官方链接 正反面引脚定义 接口含义 BLheliSuite调参软件 官方下载&#xff1a; https://www.mediafire.com/folder/dx6kfaasyo24l/BLHeliSuite 我使用了如下软件https://www.mediafire.com/file/9uccf1zy3wqb1w5/BLHeliSuite32_32.9.0.3.zip/fil…

Bio-Net:编解码器结构的循环双向连接网络

目录 摘要 方法 循环双向跳跃连接 前向跳跃连接 后向跳跃连接 递归的推断训练 BiO-Net网络结构 总结 摘要 对UNet以前的扩展主要集中对现有模块的改进或者提出新的模块来提高性能。因此这些变量通常会导致模型的复杂性不可忽视的增加。为了解决这种复杂性的问题。在本…

redis cluster 集群安装

redis cluster 集群安装 redis集群方案 哨兵集群 如图&#xff0c;实际上还是一个节点对外提供服务&#xff0c;所以虽然是三台机器&#xff0c;但是还是一台机器的并发量&#xff0c;而且master挂了之后&#xff0c;整个集群不能对外提供服务 cluster集群 多个主从集群节点…

五、伊森商城 前端基础-Vue 整合ElementUI快速开发 p28

目录 一、安装 1、安装ElementUI 2、在main.js文件中引入 2.1、引入ElementUI组件 2.2、让Vue使用ElementUI组件 二、使用 1、在hello.vue组件使用单选框 2、使用ElementUI快速搭建后台管理系统 2.1、修改App.vue 3、修改功能成动态显示 3.1、编写快速生成组件的模板 3…

java计算机毕业设计ssm学习互助平台网站8f554(附源码、数据库)

java计算机毕业设计ssm学习互助平台网站8f554&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff0…