导航


HTML

CSS

JavaScript

浏览器 & 网络

版本管理

框架

构建工具

TypeScript

性能优化

软实力

算法

UI、组件库

Node

业务技能

针对性攻坚

AI


大纲

目标

React 基础

基础概念

组件

class Welcome extends React.Component {
	render() {
		return <div>Welcome</div>
	}
}

function Welcome() {
	return <div>Welcome</div>
}

状态

// 类组件
class Welcome extends React.Component {
	constructor() {
		this.state = {
			name: 'Lance'
		};
	}
	render() {
		return <div>Welcome</div>;
	}
}

// 函数式组件
function Welcome() {
	const [count, setCount] = useState(0);
	return <div>Welcome</div>;
}

属性

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

const element = <Welcome name="Lance" />

项目初始化

项目初始化就是我们平常所说的工程化

在初始化时,我们需要考虑这个项目:

如果是企业级项目,除了技术层内容考虑以外,还需要重点关注:

通常使用脚手架,不用关心初始化的细节

vite

pnpm create vite react-vite-cli-demo --template react-ts # react ts 的模板创建方式
pnpm i
pnpm run dev

create-react-app

npx create-react-app react-cra-demo --template typescript

自搭建方案

Vite

  1. 创建项目目录并初始化

    mkdir my-react-app
    cd my-react-app
    npm init -y
    
  2. 安装 Vite 和相关依赖

    pnpm i [email protected] @vitejs/[email protected] -D
    pnpm i [email protected] [email protected]
    
    {
    	"name": "my-react-app",
    	"version": "1.0.0",
    	"description": "",
    	"type": "module",
    	"script": {
    		"dev": "vite",
    		"build": "vite build",
    		"preview": "vite preview"
    	},
    	"keywords": [],
    	"dependencies": {
    		"react": "18.3.1",
    		"react-dom": "18.3.1"
    	},
    	"devDependencies": {
    		"vite": "5.3.1",
    		"@vitejs/plugin-react": "1.0.0"
    	}
    }
    
  3. 创建 vite 配置

    import { defineConfig } from "vite" ;
    
    import react from "@vitejs/plugin-react";
    
    export default defineConfig({
    	plugins: [react()],
    	server: {
    		port: 3000,
    	}
    });
    
  4. 创建根组件和入口文件

    import { useState } from "react";
    
    function App() {
    	const [count, setCount] = useState(0);
    	return <div>123</div>
    }
    
    export default App;
    
    import React from "react";
    import ReactDOM from "react-dom/client";
    import App from "./App";
    
    ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
      <React.StrictMode>
        <App />
      </React.StrictMode>
    );
    
  5. 创建静态资源

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
      <div id="root"></div>
      <script type="module" src="/src/main.tsx"></script>
    </body>
    </html>
    

JSX

jsx 全称是:javaScript and xml,在 JavaScript 代码中编写 html 代码的一种规范。

规范是为编译器设计的。

const element = <h1>Hello, world!</h1>;

jsx 通过编译器进行转换,babel(@babel/preset-react、plugin-transform-react-jsx)

通过 jsx 转换后,代码就变成了 js 引擎可以执行的代码了。

import { jsx as _jsx } from "react/jsx-runtime";
const element = /*#__PURE__*/_jsx("h1", {
  children: "Hello, world!"
});

image.png

还没完,再在 react 运行时,通过 react 定义的 jsx 创建出 ReactElement

https://github.com/facebook/react/blob/a2329c10ffc153303ad5a65b99d91d8500ceabdd/packages/react/src/jsx/ReactJSX.js#L19

https://github.com/facebook/react/blob/a2329c10ffc153303ad5a65b99d91d8500ceabdd/packages/react/src/jsx/ReactJSXElement.js#L330

return ReactElement(type, key, props, getOwner(), undefined, undefined);

组件基础

类组件 VS 函数组件

类组件

import React from "react";

export interface BasicProps {
	name: string;
}

export interface BasicState {
	count: number;
}

export class Basic extends React.Component<BasicProps, BasicState> {
	constructor(props: BasicProps) {
		super(props);
		this.state = {
			count: 0,
		}
	}
	render() {
		return (
			<div
				onClick={() => {
					this.setState({
						count: this.state.count + 1;
					});
				}}
			>Hello, Class Component Basic! {this.state.count}</div>
		);
	}
}

函数组件

import React, { useState } from "react";

export interface BasicProps {
	name: string;
}

export const Basic: React.FC<BasicProps> = () => {
	const [count, setCount] = useState(0);
	return (
		<div onClick={() => setCount(count + 1)}>
			Hello, Functional Component Basic! {count}
		</div>
	);
}

组件属性

import React from "react";

export interface PropsProps {
	name: string;
	info: {
		age: number;
		address: string;
	};
}

export const Props: React.FC<PropsProps> = ({ name }) => {
	return <div>Hello, Functional Component Basic! {name}</div>;
}
import { Props } from "./fcc/Props";

function App() {
	return (
		<div>
			<Props name="Lance" info={{
				age: 18,
				address: 'Shanghai'
			}} />
		</div>
	);
}

组件状态

import React, { useState } from "react";

export interface StateProps {}

export const State: React.FC<StateProps> = () => {
	const [count, setCount] = useState(0); // 或者初始化函数 useState(() => 0); // 通过函数调用初始化值
	return (
		<div onClick={() => setCount(count + 1)}>
			Hello, Functional Component Basic! {count}
		</div>
	);
}

条件渲染

import React, { useState } from "react";

export interface ConditionProps {}

export const Condition: React.FC<ConditionProps> = () => {
	const [count, setCount] = useState(0);
	const contentText = count % 2 === 0 ? '偶数' : '奇数';
	return (
		<div onClick={() => setCount(count + 1)}>
			Hello, Functional Component Basic! {count} {contentText}
		</div>
	);
}

事件处理

import React, { useState } from "react";

export interface EventProps {}

export const Event: React.FC<EventProps> = () => {
	const [count, setCount] = useState(0);
	const contentText = count % 2 === 0 ? '偶数' : '奇数';
	const handleClick = (ev: React.MouseEvent) => {
		console.log("🚀 ~ handleClick ~ ev:", ev.target, ev.currentTarget);
		setCount(count + 1)
	};
	return (
		<div onClick={handleClick}>
			Hello, Functional Component Basic! {count} {contentText}
			<div
				draggable
				onDragStart={ (ev) => console.log(ev) }
				onDragEnd={ (ev) => console.log(ev) }
			>拖拽</div>
			<div
				contentEditable
				onCopy={console.log}
				onPaste={console.log}
			>我是可编辑的</div>
		</div>
	);
}

组件传值