React基础

news2024/11/26 0:50:56

文章目录

    • 1.简介
      • 1.1 react与vue
        • 1.1.1 相同点
        • 1.1.2 不同点
        • 1.1.3 函数式组件的特点(什么是函数式组件)
          • a.幂等
          • b.无副作用用:
        • 1.1.4 虚拟dom的作用
        • 1.1.5 vue当中template与render的关系:
      • 1.2 MVC、MVVM、MVP模式
        • 1.2.1 MVC
        • 1.2.2 MVVM
        • 1.2.3 MVP
    • 2.JSX
      • 2.1 预防XSS攻击
      • 2.2 JSX表示对象
    • 3.State和Props
      • 3.1 Props
      • 3.2 State
        • 3.2.1 只能通过setState赋值
        • 3.2.2 更新可能是异步
        • 3.2.3 批量更新的优化
    • 4. 生命周期
      • 4.1 旧版生命周期(react<16.0.0)
      • 4.2 新版生命周期
        • 4.3.1 挂载阶段
            • constructor
            • getDerviedStateFromProps
            • render
            • componentDidMount()
        • 4.3.2 组件更新阶段
            • shouldComponentUpdate
            • getSnapshotBeforeUpdate
            • componentDidUpdate
        • 4.3.3 组件卸载阶段
            • componentWillUnmount

1.简介

React 是一个用于构建用户界面的 JAVASCRIPT 库,主要用于构建 UI,很多人认为 React 是 MVC 中的 V。
起源于 Facebook 的内部项目,用来架设 Instagram 的网站,并于 2013 年 5 月开源。

  1. 声明式设计 −React采用声明范式,可以轻松描述应用。
  2. 高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
  3. 灵活 −React可以与已知的库或框架很好地配合。
  4. JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
  5. 组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
  6. 单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。

1.1 react与vue

1.1.1 相同点

  • 都是数据驱动视图。
  • 采用虚拟dom+diff算法,但是react16以后推出了Fiber双缓存。
  • 鼓励组件化

了解React

1.1.2 不同点

写法上: react是js的一个库,使用jsx语法,将js与html结合,更让人觉得自己在写代码;vue更像是一个前端框架,具有侵入性,有自己的语法。
核心思想上: vue为双向绑定。react推崇函数式编程,单行数据流的特性,需要双向要使用onChange和setState去实现。
diff算法: 都是按照tree这样的维度,vue从两侧像中间递归,react从左到右。
响应式原理不同:

  • react主要是通过setState()方法来更新状态,状态更新之后,组件也会重新渲染。
  • vue2.0:当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim(降级) 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。(对象属性拦截)
  • vue3.0:Vue3的响应式原理是通过Proxy来完成的。Proxy直接监听对象,而非属性,所以将多个属性转换成getter/setter的时候,不需要使用循环。(对象整体代理)

1.1.3 函数式组件的特点(什么是函数式组件)

a.幂等

只要输入值不变,输出值也不变。输出结果完全由输入决定的,输出的结果也不会因为多次调用而发生改变。
例:splice方法,两次传入值一样,返回值不一样,不满足幂等(不满足原因:改变原数组)
在这里插入图片描述
slice方法,传入值一样,返回值不变,满足幂等(没有改变原数组)
在这里插入图片描述

b.无副作用用:

不会对外界造成影响(如:发起ajax请求,设置localStorage等)。

1.1.4 虚拟dom的作用

保证性能下限。不需要手动做太多的优化,就能够开发出有一定性能的应用

1.1.5 vue当中template与render的关系:

vue默认是template渲染,可以没有render方法。vue在编译时,先去判断组件里有没有render方法,如果没有,就会把当前的template转换成render方法,最后产出的就是template里面的元素。以render为最高优先级,如果没有render就会把template转换为render。

1.2 MVC、MVVM、MVP模式

1.2.1 MVC

在这里插入图片描述

MVC是指Model、VIew和Controller:
View层: 负责显示逻辑。
Model层: 负责存储页面的业务数据,以及对应数据的操作。
Controller层: 负责应用与用户的相应操作。

当用户与页面交互, View 需要更新时,首先去找 Controller,然后 Controller 通过调用Model层,来完成对Model层的修改,然后Model层再去通知VIew层更新。

其中 View 和 Model 应用了观察者模式,当 Model 层发生改变的时候它会通知有关 View 层更新页面。

1.2.2 MVVM

在这里插入图片描述

MVVM 分为 Model、View、ViewModel:
Model: 代表数据模型,数据和业务逻辑都在Model层中定义
View: 代表UI视图,负责数据的展示
ViewModel: 负责监听Model中数据的改变并且控制视图的更新,处理用户交互操作;
Model和View并无直接联系,而是通过ViewModel来进行联系的,Model层和VIeModel层有着双向数据绑定的联系,因此Model中的数据改变时会触发View的刷新,用户在view层操作而改变的数据也会在Model层同步。

这种模式实现了Model层和View层的数据自动同步,开发者不需要自己操作DOM。

1.2.3 MVP

在这里插入图片描述
view需要更新数据时,首先去找Presenter,然后Presenter去找Model请求数据,Model获取到数据之后通知Presenter,Presenter再通知view更新。
View和Model不会直接交互,所有的交互都是由Presenter进行,Presenter充当了桥梁的作用。而Presenter必须同时拥有View和Model的对象的引用。

MVC中使用了观察者模式,当Model层发生改变时,View层更新。这样VIew层和Model层耦合在一起,当项目中逻辑变得负责是,可能造成代码混乱。

MVP中通过Presenter来实现对View层和Model层的解耦。MVC中的Controller只知道Model的接口,因此它没办法控制view层的更新。

MVP中,view层的接口暴露给了Presenter,因此可以再Present中将Model和View的变化绑定在一起,以此来实现VIew和Model的同步更新。这样就实现了View好Model的解耦。

2.JSX

JSX称为JS的语法拓展,在view层将内容书写进去,可以包含一些逻辑,通过逻辑与web组合实现一个基本的react描述。其实就是将js和html结合起来书写

2.1 预防XSS攻击

点此了解XSS攻击

2.2 JSX表示对象

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);

Babel会把JSX转移成一个名为React.createElement()函数调用

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

通过React.render,将JSX渲染为DOM

// 使⽤ReactDOM.render
const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));

3.State和Props

3.1 Props

组件无论是使用函数声明还是通过class声明,都绝不能修改自身的props
props 作为组件对外通信的一个接口,为了保证组件像纯函数一样没有响应的副作用,所有的组件都必须像纯函数一样保护它们的props不被修改

3.2 State

如果视图内的数据需要修改, 并且同时页面响应变化,我们需要将数据放在state中, 使用setState来修改数据。它是组件本身的一个作用域。

3.2.1 只能通过setState赋值

不生效(视图无法更新):

//   请不要直接修改状态值
 //   this.state.counter += 1;

3.2.2 更新可能是异步

  1. setState 只在合成事件和⽣命周期中是“异步”的,在原⽣事件和 setTimeout 中都是同步的:
    setState的“异步”并不是说内部由异步代码实现,其实本身执⾏的过程和代码都是同步的, 只是合成事件和钩⼦函数的调⽤顺序在更新之前,导致在合成事件和钩⼦函数中没法⽴⻢拿到更新后的值,形式了所谓的“异步”, 当然可以通过第二个参数 setState(partialState, callback) 中的callback拿到更新后的结果
  2. setState第一个参数可以是一个函数,这个函数的第一个参数可以拿到上一个state的值。setState的第二个参数可以是一个函数,这个函数的参数可以拿到setState改变状态之后的值

例1:


// 不生效,因为异步,第二次调用无法拿到第一次更新的值
this.setState({ counter: this.state.counter + 1 })
this.setState({ counter: this.state.counter + 1 })
this.setState({ counter: this.state.counter + 1 })

  // 生效,第一个参数可以拿到上一个state的值
  this.setState(prevState => ({
     counter: prevState.counter + 1
   }));
      this.setState(prevState => ({
     counter: prevState.counter + 1
   }));
      this.setState(prevState => ({
     counter: prevState.counter + 1
   }));

例2:

 this.setState({
            n: this.state.n + 1
        }, () => {
            //状态完成改变之后触发,该回调运行在render之后
            //可以拿到第一个参数改变之后的值
            console.log(this.state.n);
        });

3.2.3 批量更新的优化

setState 的批量更新优化也是建⽴在“异步”(合成事件、钩⼦函数)之上的,在原⽣事件和setTimeout 中不会批量更新,在“异步”中如果对同⼀个值进⾏多setState , setState 的批量更新策略会对其进⾏覆盖,取最后⼀次的执⾏(如上例1 )。
如果是同时 setState 多个不同的值,在更新时会对其进⾏合并批量更新。

componentDidMount() {
    fetchPosts().then(response => {
      this.setState({
        posts: response.posts
      });
    });

    fetchComments().then(response => {
      this.setState({
        comments: response.comments
      });
    });
  }

这里的合并是浅合并,所以 this.setState({comments}) 完整保留了 this.state.posts, 但是完全替换了 this.state.comments。

4. 生命周期

4.1 旧版生命周期(react<16.0.0)

在这里插入图片描述

import React, { Component } from "react";
export default class Lifecycle extends Component {
  constructor(props) {
    super(props);
    // 常用于初始化状态
    console.log("1.组件构造函数执行");
  }
  componentWillMount() {
    // 此时可以访问状态和属性,可进行api调用等
    console.log("2.组件将要挂载");
  }
  componentDidMount() {
    // 组件已挂载,可进行状态更新操作
    console.log("3.组件已挂载");
  }
  componentWillReceiveProps() {
    // 父组件传递的属性有变化,做相应响应
    console.log("4.将要接收属性传递");
  }
  shouldComponentUpdate() {
    // 组件是否需要更新,需要返回布尔值结果,优化点
    console.log("5.组件是否需要更新?");
    return true;
  }
  componentWillUpdate() {
    // 组件将要更新,可做更新统计
    console.log("6.组件将要更新");
  }
  componentDidUpdate() {
    // 组件更新
    console.log("7.组件已更新");
  }
  componentWillUnmount() {
    // 组件将要卸载, 可做清理工作
    console.log("8.组件将要卸载");
  }
  render() {
    console.log("组件渲染");
    return <div>生命周期探究</div>;
  }
}

4.2 新版生命周期

在这里插入图片描述

  • 挂载阶段(Mount):组件第一次在DOM树中被渲染的过程
  • 更新阶段(Update):组件状态发生变化,重新更新渲染的过程
  • 卸载过程(Unmount):组件从DOM树中被移除的过程

4.3.1 挂载阶段

constructor

组件的构造函数,第一个被执行,若没有显示定义它,会有一个默认的构造函数,但是若显示定义了构造函数,必须在构造函数中执行super(props),否则无法在构造函数中拿到this。
consturctor中通常只做两件事:

  • 初始化组件的state
  • 给事件处理方法绑定this
constructor(props) {
  super(props);
  // 不要在构造函数中调用 setState,可以直接给 state 设置初始值
  this.state = { counter: 0 }
  this.handleClick = this.handleClick.bind(this)
}
getDerviedStateFromProps

这是个静态方法,不能在这个函数里使用this,有两个参数props和state,分别指接受到的新参数和当前组件的state对象。这个函数会返回一个对象来更新当前的state对象,如果不需要可以返回null。

// 当 props.counter 变化时,赋值给 state 
class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      counter: 0
    }
  }
  static getDerivedStateFromProps(props, state) {
    if (props.counter !== state.counter) {
      return {
        counter: props.counter
      }
    }
    return null
  }
  
  handleClick = () => {
    this.setState({
      counter: this.state.counter + 1
    })
  }
  render() {
    return (
      <div>
        <h1 onClick={this.handleClick}>Hello, world!{this.state.counter}</h1>
      </div>
    )
  }
}

现在可以显示传入counter,但是如果想通过点击实现state.counter的增加,会发现值不会发生任何变化,一直保持props传进来的值。这是由于React16.4^版本中,setState和forceUpdate也会触发这个生命周期,所以当组件内部state变化后,就会重新走这个方法,同时把state赋值为props的值。解决:需要多加一个字段来记录之前的props值,这样就会解决上述问题,代码如下:

// 这里只列出需要变化的地方
class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      // 增加一个 preCounter 来记录之前的 props 传来的值
      preCounter: 0,
      counter: 0
    }
  }
  static getDerivedStateFromProps(props, state) {
    // 跟 state.preCounter 进行比较
    if (props.counter !== state.preCounter) {
      return {
        counter: props.counter,
        preCounter: props.counter
      }
    }
    return null
  }
  handleClick = () => {
    this.setState({
      counter: this.state.counter + 1
    })
  }
  render() {
    return (
      <div>
        <h1 onClick={this.handleClick}>Hello, world!{this.state.counter}</h1>
      </div>
    )
  }
}
render
  • 返回一个虚拟DOM,会被挂载到虚拟DOM树中,最终渲染到真实DOM中
  • render可能不只运行一次,只要需要重新渲染,就会重新运行
  • 严禁使用setState,因为可能会导致无限递归渲染
  • 可以返回布尔值或null 控制组件不渲染任何内容
componentDidMount()
  • 执行依赖于DOM的操作
  • 发送网络请求(官方建议)
  • 添加订阅消息(会在componentWillUnmount取消订阅)

如果在componentDidMount中调用setState,就会出发一次额外的渲染,多调用一次render函数。由于它是在浏览器刷新屏幕前执行的,所以用户是没有感知的,但是我们应该避免这样使用,这样会带来一定的性能问题,尽量在constructor中初始化state对象。

4.3.2 组件更新阶段

当组件的props改变了,或者组件内部调用了steState/forceUpdate,会触发更新重新渲染,这个过程可能会发生多次。这个过程会依次调用下面方法:

  • getDerivedStateFromProps
  • shouldComponentUpdate
  • render
  • getSnapshotBeforeUpdate
  • componentDidUpdate
shouldComponentUpdate
  • 指示react是否要重新渲染该组件,通过返回true和fasle来指定
  • 默认情况下,会直接返回true

可以比较 this.props 和 nextProps ,this.state 和 nextState 值是否变化,来确认返回 true 或者 false。当返回 false 时,组件的更新过程停止,后续的 render、componentDidUpdate 也不会被调用。
在这里插入图片描述

getSnapshotBeforeUpdate
//prevProps prevState:更新之前的props和state 
getSnapshotBeforeUpdate(prevProps, prevState)
  • 这个方法执行在rendr之后,componentDidUpdate之前(真实的DOM构建完成,但还未实际渲染到页面中)
  • 该函数的返回值,会作为componentDidUpdate的第三个参数
  • 在该函数中,通常用于实现一些附加的dom操作
    在这里插入图片描述
componentDidUpdate
// prevProps: 更新前的props
// prevState: 更新前的state
// snapshot: getSnapshotBeforeUpdate()生命周期的返回值
componentDidUpdate(prevProps, prevState, snapshot){}
  • 首次渲染不会执行此方法,更新后会被立即调用
  • 往往在该函数中使用dom操作,改变元素(也可以在此进行网络请求,例如:当props未发生变化时,则不执行网络请求)

4.3.3 组件卸载阶段

componentWillUnmount
  • 一个组件被卸载和销毁之前被调用
  • 清除 timer,取消网络请求或清除
  • 取消在 componentDidMount() 中创建的订阅等
  • 不应该在使用setState,因为组件一旦卸载,就不会装载也不会渲染

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

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

相关文章

速锐得解码特斯拉Model Y整车网关电路及CAN通信协议DBC控制策略

研究和解码特斯拉Model Y的整车控制中心的控制策略&#xff0c;比研究一般宝马、奔驰、奥迪的CAN总线数据更有乐趣&#xff0c;速锐得近期解码了特斯拉Model Y整车网关电路&#xff0c;分析出特斯拉Model Y网关电路图及CAN矩阵并编译了特斯拉Model Y通信协议DBC文件。 研究特斯…

SOLIDWORKS 3D CAD 2023基础解决方案 新功能Top 10

SOLIDWORKS 3D CAD 2023新版本即将于大家见面&#xff0c;而SOLIDWORKS 3D CAD是SOLIDWORKS整体解决方案的基础功能&#xff0c;微辰三维为您总结了SOLIDWORKS 3D CAD 2023增强功能的Top 10&#xff0c;一起来看看吧&#xff01; 1、电力布线 轻松创建含多个电路的接头&#xf…

天宇优配|上架秒光 “3时代”的大额存单受宠

“最近理财产品动摇比较大&#xff0c;准备处理一笔大额存单&#xff0c;但查询发现&#xff0c;某国有行暂时没有可购买的大额存单产品。”11月29日&#xff0c;成都市民王女士向金融出资报记者表示。 记者发现&#xff0c;虽然通过数次下调&#xff0c;中长期大额存单利率已步…

储能电源/移动电源专用升降压DC-DC方案PL9405

PL9405是一个双向同步4开关Buck-Boost变换器能够调节输出电压高于或低于输入电压。PL9405在较宽的输入电压范围内工作3.6 V至32v(最大36v)支持多种应用程序。集成两个9mΩ功率mosfet。PL9405可在1、2、3、4、5的充电模式下工作6电池充电。PL9405采用恒定ON时间控制buck&#xf…

利用phpspreadsheet导出Excel图表(折线图、饼状图、柱状图)

利用phpspreadsheet导出Excel图表安装 phpoffice/phpspreadsheet折线图需要使用的包实例代码效果图![实例图](https://img-blog.csdnimg.cn/39e32f13c52b4b40946562fdc55dc5b6.png)饼状图需要使用的包实例代码效果图柱状图需要使用的包实例代码效果图安装 phpoffice/phpspreads…

Day16-购物车页面-商品列表-渲染商品列表区域的结构

提纲挈领&#xff1a; 我的操作&#xff1a; 1》定义如下的 UI 结构&#xff1a; 2》美化样式 ***************************** ***************************** ***************************** ********************* 2.渲染商品列表区域的基本结构 我的操作&#xff1a; 1》…

网页添加灰色滤镜

网页添加灰色滤镜 b站的灰色滤镜 我校的灰色滤镜 CSDN的灰色滤镜 自己调制css主题,给网页加上滤镜. 更快捷的,可以在可以调制css的浏览器插件中加上滤镜,只要开启插件就会自动修改网站滤镜 以darkreader为例打开其开发者工具 *INVERT .jfk-bubble.gtx-bubble .captcheck_a…

推荐系统-召回-概述(三):向量化

只要对机器学习稍有涉猎&#xff0c;就会发现如今机器学习&#xff0c;无论是推荐、图像、语言等领域&#xff0c;随处可见embedding&#xff0c;可以说&#xff0c;在深度学习主宰机器学习领域的今天&#xff0c;万物皆可embedding。那么&#xff0c;什么是embedding&#xff…

SpringCloud-alibaba-Sentinel入门到精通

膜拜大神的全集&#xff1a; sentinel &#xff08;史上最全&#xff09;_40岁资深老架构师尼恩的博客-CSDN博客_sentinel 1、什么是Sentinel: Sentinel是阿里开源的项目&#xff0c;提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。 官网&#x…

智能聊天机器人如何帮助独立站运营提高工作效率?

关键词&#xff1a;智能聊天机器人、独立站运营 独立站运营变得越来越受欢迎&#xff0c;独立站可以用来建立在线商店并推动您的电子商务业务取得成功。它具有大量以业务为中心的功能&#xff0c;也许这就是为什么许多公司相信它会发展其在线业务的轨迹。 添加聊天机器人可以进…

使用PyQt5界面设计

一、环境搭建 直接pip安装即可&#xff1a; pip install PyQt5 pip install pyqt5-tools 二、Qt Designer设计GUI Qt Designer 是通过拖拽的方式放置控件&#xff0c;并实时查看控件效果进行快速UI设计。最终生成.ui文件&#xff0c;可以通过pyuic5工具转换成.py文件。 打开d…

基于springboot的应用诊断工具,yyds

真正的大师,永远都怀着一颗学徒的心&#xff01; 一、项目简介 基于springboot的应用诊断工具&#xff0c;可以迅速定位出来线上运行项目的问题。 二、实现功能 支持服务器管理 支持权限管理 支持系统诊断 支持代码在线编辑部署 支持各种方法的监控 支持线程的管理 三、…

【自然语言处理(NLP)】基于Word2Vec的语言模型实践

【自然语言处理&#xff08;NLP&#xff09;】基于Word2Vec的语言模型实践 作者简介&#xff1a;在校大学生一枚&#xff0c;华为云享专家&#xff0c;阿里云专家博主&#xff0c;腾云先锋&#xff08;TDP&#xff09;成员&#xff0c;云曦智划项目总负责人&#xff0c;全国高等…

jenkins学习-安装配置

1.下载安装 打开地址jenkins.io,进入页面&#xff0c;点击download按钮&#xff0c;计入下载页面&#xff0c;选择war架包下载 2.下载地址2&#xff1a;https://get.jenkins.io/war/ 下载版本&#xff1a;2.346.3 3控制台切换到架包路径&#xff0c;执行&#xff1a;Java -…

Java学习之super关键字

目录 一、super的作用 二、基本语法 第一条 第二条 第三条 三、super便利/细节 第一条 第二条 第一种&#xff1a;直接调用 第二种&#xff1a;this 第三种&#xff1a;super 第三条 四、this和super的比较 一、super的作用 super 代表父类的引用&#xff0c; 用于访…

Vue3表单输入绑定生命周期

官网&#xff1a;https://cn.vuejs.org/guide/essentials/forms.html#checkbox 复选框 在这个例子中&#xff0c;checkedNames 数组将始终包含所有当前被选中的框的值。 const checkedNames ref([])<div>Checked names: {{ checkedNames }}</div><input type…

docker镜像打包上传阿里云镜像仓库

阿里云镜像仓库说明&#xff1a; 将镜像推送到Registry $ docker login --usernamealiyun0398513152 rz-dt-image-server-registry.cn-shanghai.cr.aliyuncs.com $ docker tag [ImageId] rz-dt-image-server-registry.cn-shanghai.cr.aliyuncs.com/rz-dt/k8s-springboot-demo:[…

澜起科技发布业界首款DDR5第三子代寄存时钟驱动器工程样片

上海—2022年12月1日&#xff0c;澜起科技宣布在业界率先推出DDR5第三子代寄存时钟驱动器&#xff08;简称RCD或DDR5 RCD03&#xff09;工程样片&#xff0c;并已向业界主流内存厂商送样&#xff0c;该产品将用于新一代服务器内存模组。 澜起科技DDR5第三子代寄存时钟驱动器 D…

堆排序和Top-K问题(C语言实现)

文章目录&#xff1a;1.堆排序1.1向上调整和向下调整建堆对比1.2堆排序实现1.2.1升序1.2.2降序2.Top-K问题2.1解决思路2.2代码实现前面的文章讲了堆的结构和基础接口实现&#xff0c;不熟的友友们可以去看看堆&#xff08;C语言实现&#xff09;&#xff0c;点击跳转 1.堆排序 …