普通视图

发现新文章,点击刷新页面。
昨天以前首页

【React专栏】一、React基础(一)

作者 engineer_why
2025年6月26日 18:50

React基础

1.1 React项目创建

npm install -g create-react-app

1.2 JSX语法

  • 使用成对的标签构成一个树状结构的数据

  • 当使用DOM类型标签时,标签的首字母必须小写

  • 当使用React组件类型标签时,标签的首字母必须大写

    • 因为React正是通过标签的首字母大小写,来判断当前是一个DOM类型标签,还是React组件类型标签。
  • 可以使用JavaScript表达式,因为JSX本质上仍是JavaScript

    • 在JSX中使用JavaScript表达式,需要用大括号“{}”包起来
    • 使用场景
      • 1️⃣通过表达式给标签属性赋值
      • 2️⃣通过表达式定义子组件
  • JSX中只能使用JavaScript表达式,不能使用多行JavaScript语句

  • 可以使用三元运算符或逻辑与(&&)运算符 代替 if 语句 的作用

  • JSX是DOM类型标签时,对应DOM标签支持的属性JSX也支持。

    • 但部分属性名称会改变,主要变化有:
      • class --> className(因为class时JavaScript的关键字)
      • onclick --> onClick(React对DOM标签支持的事件做了封装,封装时采用更常用的驼峰式命名法命名事件)
  • JSX标签是React组件类型时,可以任意自定义标签的属性名

  • JSX中的注释,需要用大括号“{}”将/* 注释 */包裹起来

const element = {
    <div>
        {/* 这是注释 */}
        <span>React</span>
   </div>
}

1.2.1 JSX 不是必需的

  • JSX语法只是 React.createElement(component, props, ...children)的语法糖,所有的JSX语法最终都会被转换成对这个方法的调用。
// JSX 语法
const element = <div className='foo'>Hello,React</div>

// 转换后
const element = React.createElement('div',{className: 'foo'},'Hello,React')

1.3 组件

React应用程序正是由一个个组件搭建而成。

1.3.1 组件定义

组件定义有两种方式: 1️⃣ES6 class(类组件) 2️⃣使用函数(函数组件)

1.3.1.1 类组件
  • 使用class定义组件,需要满足两个条件
    • class继承自React.Component
    • class内部必须定义render方法,render方法返回代表该组件UI的React元素
  • 创建好的React组件,需要使用ES6 export导出,方便其他文件引入
  • 渲染至页面,还需要使用到 react-dom 库中的 render函数(这个库会完成组件所代表的虚拟DOM节点到浏览器的DOM节点的转换)
import ReactaDOM from "react-dom";
import PostList from "./PostList";

ReactDOM.render(<PostList />, document.getElementById("root"));
1.3.1.2 函数组件

方便用于定义 无状态组件(即无需定义 state,仅接收props)

function Welcome(props) {
    return <h1>Hello,{props.name}</h1>
}

1.3.2 组件的 props

组件的props用于把 父组件中的数据或方法 传递给子组件,供子组件使用。

1.3.3 组件的 state

  • 组件的 state 是组件内部的状态,state 的变化最终将反应到组件的UI变化上。
  • 通过组件的构造方法 constructor 中,通过 this.state 定义组件的初始化。
  • 通过调用 this.setState 方法改变组件的状态(唯一改变组件状态的方式),组件UI会重新渲染

在组件的构造方法 constructor 内,首先要调用 super(props),这一步实际上是调用 React.Component 这个 class 的 constructor 方法,用来完成React组件的初始化工作。

小结: React 组件正是由 props 和 state 两种类型的数据,驱动渲染组件。props 是组件对外的接口,通过 props 接收外部传入的数据和方法; state 是组件内部的接口,组件内部的状态变化通过 state 反映。props 是只读的,不允许更改; state 是可变得,组件状态变化可通过改变 state 来实现。

1.3.4 有状态组件和无状态组件

React 应用组件设计的一般思路是,通过定义少数的有状态组件,管理整个应用的状态变化,并且将状态通过 props 传递给其余的无状态组件,由无状态组件完成页面的大部分 UI的渲染工作

  • 应尽可能多的使用无状态组件,无状态组件无需关心状态的变化,只聚焦UI的展示,更容易被复用。
  • 有状态组件主要处理状态变化的业务逻辑,无状态组件主要关注UI的渲染。

1.3.5 属性校验和默认属性

  • 属性校验
    • 基本的属性校验类型

      • String --> PropTypes.string
      • Number --> PropTypes.number
      • Boolean --> PropTypes.bool
      • Function --> PropTypes.func
      • Object --> PropTypes.object
      • Array --> PropTypes.array
      • Symbol --> PropTypes.symbol
      • Element --> PropTypes.element
      • Node --> PropTypes.node (可被渲染的节点:数字、字符串、React 元素或由这些类型的数据组成的数组)
    • 当知道要校验的属性是一个对象或数组时,通过使用PropTypes.shape(校验对象结构,校验内部属性类型)或PropTypes.arrayOf(校验数组内部元素类型)

style: PropTypes.shape({
    color: PropTypes.string;
    fontSize: PropTypes.number;
}),
sequence: PropTypes.arrayOf(PropTypes.number);

// 表示 style 是一个对象,对象内有 color 和 fontSize 两个属性, 
// color 是字符串类型,fontSize 是数字类型;sequence 是一个数组,数组的元素是数字类型。
  • 必填校验
    • 需要在PropTypes 的类型属性上,调用isRequired。
PostItem.propTypes = {
    post: PropTypes.shape({
        id: PropTypes.number
    }).isRequired,
    onVote: PropTypes.func.isRequired
}
  • 属性默认值
    • 通过组件的defaultProps 实现。当组件属性未被赋值时,组件会使用 defaultProps 定义的默认属性。
function Welcome(props) {
    return <h1 className='foo'>Hello, {props.name}</h1>
}

Welcome.defaultProps = {
    name: 'Stranger'
}

// 当props.name 未被赋值时,使用下方定义的默认属性值

【TypeScript专栏】二、TypeScript基础(一)

作者 engineer_why
2025年6月26日 18:41

2.1 JavaScript 基础知识补充

  • 数据类型

    • 7种原始类型

      • Boolean 布尔
      • Null 空
      • Undefined 未定义
      • Number 数字
      • BigInt 任意精度的整数

        它解决了传统 Number 类型因使用 64 位浮点数格式而无法安全表示超大整数(超过 ±(2^53 - 1))的问题。

      • String 字符串
      • Symbol 唯一
    • Object

      除 Object 以外的所有类型都是不可变的(值本身无法被改变)。称这些类型的值为“原始值”。

  • 类数组

    • 是普通对象,具有 length 属性和数字索引访问能力,但不继承 Array.prototype,因此无法直接调用数组方法。

    • 区别

      • 数组:是 JavaScript 的内置对象,用于存储有序的元素集合,继承自 Array.prototype,拥有丰富的数组方法(如 pushmapforEach 等)。
      • image.png
    • 转换为数组的方法

      // Array.from() (推荐)
      const argsArray = Array.from(arguments);
      
      // 扩展运算符 ...
      const nodesArray = [...doucment.querySelectorAll('div')];
      
      // Array.prototype.slice.call() (旧版本兼容)
      const argsArray = Array.prototype.slice.call(arguments);
      

2.2 原始数据类型

// 布尔类型
let isDone: boolean = false;

// 数字类型
let age: number = 12;

// 字符串类型
let firstName: string = 'zhangsan';
let message: string = `Hello,${firstName}`

// null 和 undifined
// 这两种类型是所有类型的子类型
// 也就是说这两种类型值可以赋值给其他类型
let u: undefined = undefined;
let n: null = null;

2.3 Any类型

  • 在无法判断所写数据的类型时,或临时完善ts校验时,可用。
  • 允许赋值给任意类型。
  • 一般情况下,要避免使用any类型,因为这个类型可以任意调用方法和属性,就会更容易出现错误,丧失类型检查的作用。
let notSure: any = 4;
notSure = 'maybe a string';
notSure = true;

notSure.myName;
notSure.getName(); 
// 调用属性和方法均不会报错,因为默认为any 任意类型

2.4 数组

// 声明 数字类型的数组
// 数组的元素,不允许出现 数字以外的类型
let arrOfNumber: number[] = [1,2,3];

// 在指定好类型后,在调用这个数组后
// 可以自动获得数组上所有的方法
// (输入 数组名.  后,存在的方法会自动弹出提示框)
arrOfNumber.push(5);

image.png

2.5 类数组

function test() {
    console.log(arguments);
    // arguments 就是类数组
    // 而类数组有已经内置的类型 IArguments 类型
    // 还有诸多已经存在的内置类型
}

2.6 元组

  • 合并不同类型的对象 将内部的数据类型进行更精细的确定
  • 起源于函数式编程
// 存储的数组元素,顺序和类型必须对应
// 因为仍旧是数组,所以可以使用数组的方法
// 如 push,但只可添加设定好的两种类型的值
let user: [string, number] = ['zhangsan', 20];
❌
❌