React总结1

news2024/11/18 1:40:14

3 React技术

React是Facebook于2013年开源的框架。React解决的是前端MVC框架中的View视图层的问题。

3.1 Virtual DOM*

DOM(文档对象模型Document Object Model)
将网页内所有内容映射到一棵树型结构的层级对象模型上,浏览器提供对DOM的支持,用户可以是用脚本调用DOM API来动态的修改DOM结点,从而达到修改网页的目的,
这种修改是浏览器中完成,浏览器会根据DOM的改变重绘改变的DOM结点部分。
修改DOM重新渲染代价太高,前端框架为了提高效率,尽量减少DOM的重绘,提出了Virtual DOM,所有的修改都是现在VirtualDOM上完成的,通过比较算法,
找出浏览器DOM之间的差异,使用这个差异操作D0M,浏览器只需要渲染这部分变化就行了。

React实现了DOM Diff算法可以高效比对Virtual DOM和DOM的差异。

Virtual DOM实际上就是内存中的一个数据结构、对象,本身不属于浏览器,而是在浏览器中通过js引擎构建出来的一个对象。不管怎么样,都是在浏览器中跑得东西,和服务器端没什么关系。

前后端,一般前后端指的是web的前后端,前端往往指的是浏览器,后端指的是wsgi、server这些东西

前端技术,通常指浏览器中能够跑的东西:CSS,HTML,JS

3.2 支持JSX语法

JSX是一种JavaScript和XML混写的语法,是JavaScript的扩展。

React.render(
    <div>
        <div>
            <div>content</div>
        </div>
    </div>,
    document.getElementById('example')
)

3.3 测试程序

替换src/index.js程序

// 基于React框架,使用JSX语法,替换上述代码
// 1、导入react模块
import React from "react";  // 导入react模块
import ReactDOM from "react-dom";  // 导入react的DOM模块

// 2、创建React元素
class Root extends React.Component{ // 组件类定义,从React.Component类上继承,这个类生成JSXElement对象,即React元素
  state = {
    p1: "www.baidu.",
    p2: "com"
  } // 每一个react组件component都有一个状态变量state,它是一个js对象,可以定义属性来保存值。如果状态发生变化,会触发UI重新渲染。state是组件内部的私有属性
  render(){ // 渲染函数,返回组件中渲染的内容, 注意,只能返回唯一一个顶级元素回去
    console.log("render log");
    setTimeout(() => this.setState({p2: "net"}), 3000); // 延时函数:设置异步修改状态  // state的变化,会触发调用render,所以,render内最好不要对state进行任何改变,虽然可以,但是尽量不要。
    // this.state.p2 = "net"
    return <div>{this.state.p1 + this.state.p2}</div>;  // div是一个容器,可以包含其他html标记。这里只能包含一个顶级元素
  }
}

// 3、将React元素添加到DOM的Element元素中并渲染
ReactDOM.render(<Root/>, document.getElementById('root'));  // 渲染,将组件类挂载到DOM树中要被渲染的元素中去。第一个参数是JSXElement对象;第二个参数是DOM的Element元素。指定DOM树中被渲染的元素id,将React元素对DOM树中的元素进行替换并重新渲染。

// 4、保存后文件自动编译
  • html中的元素分类:
    学习html后, 你会了解一些基本的html元素(Element), 如p, h1~h6, br, div, li, ul, img等.如果将这些元素细分, 又可以分别归为顶级 (top-level)元素,块级 (block-level)元素和内联 (inline)元素.

1、Top-level element 【顶级元素】: { html, body, frameset }。包括html, body, frameset, 表现如Block-level element, 属于高级块级元素.
2、Block-level element 【块级元素】: { p, h1~h6, div, ul }。顾名思义就是以块显示的元素,高度宽度都是可以设置的。比如我们常用的 p, h1~h6, div, ul 默认状态下都是属于块级元素。块级元素比较霸道,默认状态下每次都占据一整个行,后面的内容也必须再新起一行显示。当然非块级元素也可以通过css的 display:block;将其更改成块级元素。此外还有个特殊的,float也具有此功能。块级元素能够独立存在, 一般的块级元素之间以换行(如一个段落结束后另起一行)分隔。块级元素是构成一个html的主要和关键元素, 而任意一个块级元素均可以用Box model来解释说明.
3、Inline element 【内联元素】: { a, br, em, img, li, span }通俗点来说就是文本的显示方式,与块级元素相反,内联元素的高度宽度是不可以设置的,其宽度就是自身文字或者图片的宽度。我们常用到的<a>、<span>、<em>都属于内联元素。内联元素的显示特点就是像文本一样的显示,不会独自占据一个行。 当然内联元素也能变成块级元素,那就是通过css的display:inline;和float来实现。内联元素依附其他块级元素存在, 紧接于被联元素之间显示, 而不换行.

注意:
1、React组件的render函数return,只能是一个顶级元素。组件是最小封装对象
2、JSX语法是XML,要求所有元素闭合,注意<br />不能写成<br>

3.4 JSX规范*

首字母小写就是html标记,首字母大写就是组件。
要求严格的HTML标记,要求所有标签都必须闭合。br也应写成<br />,/前留一个空格。
单行省略小括号,多行请使用小括号
元素有嵌套,建议多行,注意缩进
JSX表达式:使用{}扩起来,如果大括号内使用了引号,会当做字符串处理。例如:<div>{'2>1?true:false'}<div/>


3.5 组件状态state*

每一个react组件component都有一个状态变量state,它是一个js对象,可以定义属性来保存值。
如果状态发生变化,会触发UI重新渲染。
state是组件内部的私有属性。

class Root extends React.Component{ // 组件类定义,从React.Component类上继承,这个类生成JSXElement对象,即React元素
  state = {
    p1: "www.baidu.",
    p2: "com"
  } // 每一个react组件component都有一个状态变量state,它是一个js对象,可以定义属性来保存值。如果状态发生变化,会触发UI重新渲染。state是组件内部的私有属性
  render(){ // 渲染函数,返回组件中渲染的内容
    console.log("render log");
    // this.setState({p2: "net"}); // 不可以对还在更新中的state使用setState
    setTimeout(() => this.setState({p2: "net"}), 3000); // 延时函数:设置异步修改状态,和上一行是两码事。
    // this.state.p2 = "net"
    return <div>{this.state.p1 + this.state.p2}</div>;  // div是一个容器,可以包含其他html标记。这里只能包含一个顶级元素
  }
}
  • state的变化,会触发调用render,所以,render内最好不要对state进行任何改变,虽然可以,但是尽量不要。
  • 延时函数:设置异步修改状态

3.6 复杂状态

将本目录中’./test.html’使用jsx进行替换。
可以将’./test.html’文件移动到上一层目录下,然后在浏览器中http://localhost:3000/test.html 进行访问查看效果。

class SubElement extends React.Component{
  render(){
    return <div>这是子元素SubElement</div>
  }
}


class Trigger extends React.Component{
  state = {
    flag: true
  }
  handlerClick(event){
    console.log("触发的事件ID为:" + event.target.id)
    alert("点击这里触发事件,事件ID为" + event.target.id)
    this.setState({flag: !this.state.flag})
  }
  render(){
    let x = this.state.flag?'true':'false';
    return (<div id="trig" onClick={this.handlerClick.bind(this)}>
      定义一个html标记div,div是分组,给这个标记起名字ID为trig,并注册一个事件onClick,事件捆绑一个函数handlerClick函数.当鼠标点击时,触发事件。
    事件一被触发立即调用与该事件绑定的函数,同时送一个参数进去, 这个参数不用管,这个参数是浏览器对象(event对象),由浏览器自动传入
      <SubElement/>
      {x}
    </div>)
  }
}

ReactDOM.render(<Trigger/>, document.getElementById("root2"))

3.7 props属性*

props,使得可以从外部给React组件传递数据。传入的这个数据如果是对象,还可以访问、修改对象的属性。
props的属性是只读的,不允许修改。

import React from "react";
import ReactDOM from "react-dom";

class SubElement extends React.Component{
  render(){
    console.log(this.props.name)
    console.log(this.props.parent, 'SubElement.props.parent.state.flag=' + this.props.parent.state.flag) // 还可以通过props传递的对象,修改、访问外层对象的元素
    
    return <div>这是子元素SubElement {this.props.children} {/*演示通过子元素,给props的children元素增加的属性*/}</div>
  }
}


class Trigger extends React.Component{
  state = {
    flag: true
  }
  handlerClick(event){
    alert("点击这里触发事件,事件ID为" + event.target.id)
    this.setState({flag: !this.state.flag})
    // this.props.name = "Trigger" // props元素只读,不允许修改
  }
  render(){
    let x = this.state.flag?'true':'false';
    return (<div id="trig" onClick={this.handlerClick.bind(this)}>
      <SubElement name="我是subElement" parent={this}>
        <hr />
        <div>我是subElement的children的元素</div> {/*演示通过子元素传入数据到props的children元素中*/}
      </SubElement>  {/*利用props属性,从组件外部给组件内部传递数据。这里的数据会保存到props属性中*/}
      点击这里触发一个事件,会弹出警告对话框。
    </div>)
  }
}

ReactDOM.render(<Trigger/>, document.getElementById("root2"))

总结

  • state是私有private属性,组件外无法直接访问,可以修改state,建议使用setState。
  • props是公有public属性,组件外也可以访问,只读。
  • 代码示例中,name="我是subElement",这个属性作为单一对象传递给组件,加入到组件的props属性中;parent={this},这里的this是Trigger组件本身。
  • 在Trigger中,使用JSX语法增加子元素,这些子元素,也会被加入到subElement的props.children中

3.8 构造器constructor

ES6使用构造器,为组件添加属性

import React from "react";
import ReactDOM from "react-dom";


class Trigger extends React.Component{
  // state = {flag: true}
  constructor(props){ /*ES6使用构造器,为组件添加属性。通过构造器添加属性,使代码可读性更好*/ 
    super(props); // 调用父类的constructor,需传入props属性。
    this.state = {flag: true}
  }

  handlerClick(event){
    alert("触发事件的ID为" + event.target.id)
    this.setState({flag: !this.state.flag})
  }
  render(){
    return (<div>点击这里触发一个事件,会弹出警告对话框。</div>)
  }
}

3.9 组件的生命周期管理*

组件的声明周期可分为三个状态:

  • Mounting: 挂载,表示组件已插入到真实的DOM树中
  • Updating: 正在本重新渲染
  • Unmounting: 已从真实的DOM树中移除

组件的生命周期状态,说明在不同时机访问组件,组件正处在生命周期的不同状态上。在不同的声明周期状态访问,就产生不同的方法。

生命周期的方法如下:

  • 装载组件触发

    • componentWillMount 在渲染前调用,在客户端也在服务端。只会在装载之前调用一次。

    • componentDidMount:在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout,setInterval或者发送AJAX请求等操作(防止异部操作阻塞U1)。只在装载完成后调用一次,在render之后。

  • 更新组件触发。这些方法不会在首次render组件的周期调用

    • componentWillReceiveProps(nextProps)在组件接收到一个新的prop时被调用。这个方法在初始化render时不会被调用。

    • shouldComponentUpdate(nextProps,nextState)返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。

      可以在你确认不需要更新组件时使用。
      如果设置为false,就是不允许更新组件,那么componentWillUpdate、componentDidUpdate不会执行。

    • componentWillUpdate(nextProps, nextState)在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。

    • componentDidUpdate(prevProps,prevState)在组件完成更新后立即调用。在初始化时不会被调用。

  • 卸载组件触发

    • componentWillUnmount在组件从DOM中移除的时候立刻被调用。

在这里插入图片描述

从上图可以看出:

  • constructor构造器是最早被执行的函数
  • 要触发更新声明周期函数,需要更新stateprops

3.10 无状态组件*

从React15.0开始,支持无状态组件。定义为:

import React from "react";  // 导入react模块
import ReactDOM from "react-dom";  // 导入react的DOM模块

function Root(props){
  return <div>{props.name}</div>;
}

ReactDOM.render(<Root name={"test"}/>, document.getElementById("root"));

无状态组件也叫函数式组件。
开发中很多情况下,组件其实很简单,不需要state状态,也不需要使用生命周期函数。无状态组件很好的满足了需求。

  • 无状态组件函数应该提供一个参数props,返回一个React元素。
  • 无状态组件函数本身就是render函数。

改写定义代码为:

import React from "react";  // 导入react模块
import ReactDOM from "react-dom";  // 导入react的DOM模块

let ROOT = props => <div>{props.name}</div>;
ReactDOM.render(<Root name={"test"}/>, document.getElementById("root"));

总结

react中,虚拟dom有可能会被文档。组件的state、props、生命周期一般都会被问,需要理解。

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

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

相关文章

构建全面 AI Agent 解决方案:Chocolate Factory 框架的文本到 UI、图表和测试用例生成...

长太不看版&#xff1a;基于领域驱动设计思考的 AI Agent 框架 Chocolate Factory&#xff0c;框架现在还在 PoC 阶段&#xff0c;欢迎加入开发。&#xff08;当前主要关注于 SDLC AIGC 的场景&#xff09;。 GitHub&#xff1a;https://github.com/unit-mesh/chocolate-facto…

MySQL的架构和性能优化

一、架构 MySQL逻辑架构整体分为三层&#xff0c;最上层为客户端&#xff0c;并非MySQL独有&#xff0c;诸如&#xff1a;连接处理&#xff0c;授权认证&#xff0c;安全等功能均在这一层处理 MySQL大多数核心服务均在中间这一层&#xff0c;包括查询解析&#xff0c;分析优化…

【Mysql】数据库第三讲(表的约束、基本查询语句)

表的约束和基本查询 1.表的约束1.1 空属性1.2默认值1.3列描述1.4 zerofill1.5主键1.6 自增长1.7 唯一键1.8外键 1.表的约束 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c; 需要有一些额外的约束&#xff0c; 更好的保证数据的合法性&#xff0c;从…

【Flowable】FlowableUI使用以及在IDEA使用flowable插件(二)

前言 之前有需要使用到Flowable&#xff0c;鉴于网上的资料不是很多也不是很全也是捣鼓了半天&#xff0c;因此争取能在这里简单分享一下经验&#xff0c;帮助有需要的朋友&#xff0c;也非常欢迎大家指出不足的地方。 一、部署FlowableUI 1.准备war包 在这里提供了&#xf…

Java之Hashset的原理及解析

4.数据结构 4.1二叉树【理解】 二叉树的特点 二叉树中,任意一个节点的度要小于等于2 节点: 在树结构中,每一个元素称之为节点 度: 每一个节点的子节点数量称之为度 二叉树结构图 4.2二叉查找树【理解】 二叉查找树的特点 二叉查找树,又称二叉排序树或者二叉搜索树 每一…

【算法专题突破】双指针 - 最大连续1的个数 III(11)

目录 1. 题目解析 2. 算法原理 3. 代码编写 写在最后&#xff1a; 1. 题目解析 题目链接&#xff1a;1004. 最大连续1的个数 III - 力扣&#xff08;Leetcode&#xff09; 这道题不难理解&#xff0c;其实就是求出最长的连续是1的子数组&#xff0c; 但是&#xff0c;他支…

[学习笔记]PageRank算法

参考资料&#xff1a;改变世界的谷歌PageRank算法 pagerank算法用于计算节点重要度 思想 如果网页被更多的入度(被引用)&#xff0c;则网页更重要。 被重要网站引用比被普通网站引用更加凸显重要性。 所以考虑一个网站是否重要&#xff0c;需要看引用它的网站是否重要&#…

Mysql binlog的三种模式statement,row,mixed详解,以及无主键造成复制延时的测试

2.1 Statement 模式的概念 Statement 是基于语句的复制模式。 Statement 模式将数据库中执行的修改操作记录为 SQL 语句&#xff0c;再从数据库上执行相同的 SQL 语句来实现数据同步。 2.2 Statement 模式的优点 Statement 模式的优点是简单明了&#xff0c;易于理解和实现。…

工作不好找,普通打工人如何破局

大家好&#xff0c;我是苍何&#xff0c;我的一位阿里朋友被裁后&#xff0c;找工作找了一个月都没结果&#xff0c;很多到最后一面被pass了&#xff0c;不由得做一下感慨&#xff0c;即使是大厂背景又如何&#xff0c;面对经济环境和大环境市场&#xff0c;每个人都不容易。 …

关于一个left join的易错点

很多人在学习mysql的时候应该都出现过很多问题&#xff0c;特别是连接方面的问题应该最多&#xff0c;希望这篇文章帮助到正在找bug的你 Java报错数据返回数量出现错误 遇到这种问题一定要看日志 很明显通过left join查询除了两条数据并且为空 马上思考错误的原因&#xff0c;…

【playwright】访问不同链接方法

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 访问不同页面方法方法比较 browser.new_page() page context.new_page() 1. 访问不同url 1.1 方法一 browser.new_page() 打开多个浏览器&#xff0…

JS如何判断一个变量是否为数组类型?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用 Array.isArray() 方法⭐ 使用 instanceof 操作符⭐ 使用 Object.prototype.toString.call() 方法⭐ 使用 Array.from() 方法⭐ 使用 Array.prototype.isArray 属性&#xff08;不推荐&#xff09;⭐ 写在最后 ⭐ 专栏简介 前端入门之…

人机融合的熵增定律

在信息论中&#xff0c;熵增定律是指在信息传输或处理过程中&#xff0c;总的熵&#xff08;即不确定性或信息的度量&#xff09;通常会增加。然而&#xff0c;对于人机融合的情况&#xff0c;熵增定律并不是一个普适的定律&#xff0c;而是取决于具体情境和应用。 当人与机器进…

uniapp-小程序登录授权框

微信官方文档 不弹出授权框原因 因为版本问题&#xff0c;目前的最新的版本是不支持 wx.getUserInfo 去主动弹出授权框 只能引导用户去点击 butten 去授权 解决方法 我的思路是参考了其他的微信微信小程序, 就是跳转到我的页面的时候 在钩子函数内去触发一个封装的模态框,状…

STM32-HAL库07-软件SPI驱动0.96寸OLED

STM32-HAL库07-软件SPI驱动0.96寸OLED 一、所用材料&#xff1a; STM32VGT6自制控制板 STM32CUBEMX&#xff08;HAL库软件&#xff09; MDK5 二、所学内容&#xff1a; 通过HAL库配置四个GPIO输出口&#xff0c;对其进行软件模拟SPI发送规则&#xff0c;进而驱动OLED进行数…

VisualStudio Code 支持C++11插件配置

问题 Visual Studio Code中的插件: Code Runner 支持运行C、C、Java、JS、PHP、Python等多种语言。 但是它不支持C11特性的一些使用&#xff0c;比如类似错误&#xff1a; binarySearch.cpp:26:17: error: non-aggregate type ‘vector’ cannot be initialized with an ini…

C++(day4)

思维导图 封装Mystring #include <iostream> #include<cstring>using namespace std;class Mystring{ public://无参构造函数Mystring():size(10){strnew char[size];strcpy(str,"");cout<<"无参构造函数"<<endl;}//有参构造函数…

前端内存泄漏和溢出的情况以及解决办法

写在前面&#xff1a; 在平时写代码时&#xff0c;内存泄漏的情况会时有发生&#xff0c;虽然js有内存回收机制&#xff0c;但在平时编程中还是需要注意避免内存泄漏的情况&#xff1b;前几天做移动端时遇到一个内存泄漏造成移动端页面卡顿的问题&#xff0c;所以想总结下前端…

GO语言网络编程(并发编程)Channel

GO语言网络编程&#xff08;并发编程&#xff09;Channel 1、Channel 1.1.1 Channel 单纯地将函数并发执行是没有意义的。函数与函数间需要交换数据才能体现并发执行函数的意义。 虽然可以使用共享内存进行数据交换&#xff0c;但是共享内存在不同的goroutine中容易发生竞态…

Linux Debian12使用git将本地项目打标签、创建分支和分支合并到master再上传到码云(gitee)远程仓库

一、git创建分支并克隆指定分支到本地 gitee官网&#xff1a;https://gitee.com/ 登录上gitee账号,我这用test仓库作测试。新建分支名称为develop&#xff0c;分支起点选择master&#xff0c;创建即可&#xff0c;如下图所示&#xff1a; 使用git管理代码版本时&#xff0…