CZX前端秘籍3
TS
JS弱类型语言 TS强类型语言(进行类型约束)
类型推断
类型注解
let str: string = 'abc'
类型断言
let numArr = [1,2,3]; const result = numArr.find(item => item > 2) as number; result * 5
基础类型
let v1:string = 'abc'; let v2:number= 10;
联合类型
let v3:string|number = 10; let v4: 1 | 2 | 3 = 2
数组
let arr:number[] = [1,2,3]; let arr:Array<string> = ['a', 'b', 'c']
元组
let t1:[number,string,number?] = [1,'a']
枚举
enum myEnum(A, B, C); console.log(myEnum.A, myEnump[0]);
函数
function myFn(a:10, b:string, c:boolean, ...d:number[]):number{ return 100 }
接口
interface obj{ name: string, age:number }; const obj1:obj = { name: 'a', age: 10 }
类型别名
type MyUserName = string | number; let a:MyUserName
泛型
function myFn<T>(a:T, b:T):number{ return [a,b] }; myFn<number>(1,2); myFn<string>('a','b')
接口和类型别名
1 都能描述基本对象(描述一个字段,可能有多种属性,只能使用类型别名 type)
interface IPerson{
name: string
age: number
}
type TPerson{
name: string
age: number
}
const person: TPerson = { name: 'i47', age: 18 }
// 描述一个字段,可能有多种属性,只能使用类型别名 type
// 期待描述一个性别,可能是数字或字符串,只能使用类型别名 type
type aaa = string | number
const sex: aaa = 0
2 都能进行类型拓展(interface 用 extends,type 用 & 形成交叉类型)
interface I2d {
x: number
y: number
}
interface I3d extends I2d {
z: number
}
const the3: I3d = {
x: 4, y: 5, y: 6
}
type T2d = {
x: number
y: number
}
type T3d = T2d & {
z: number
}
const the3: T3d = {
x: 4, y: 5, y: 6
}
3 名字相同时的表现(相同的interface会合并,相同的type会报错)
interface I2d {
x: number
}
interface I2d {
y: number
}
=>
interface I2d {
x: number
y: number
}
----------------------------------
type T2d {
x: number
}
type T2d {
y: number
}
=> 报错
泛型是一种在定义函数、类或接口时使用类型参数的方式,以增加代码的灵活性和重用性。
any
unknown never
在 TypeScript 中,any
和 unknown
都是用于处理不确定类型的值。
unknown类型比any类型安全,但unknown类型不能调用它的属性和方法。
let m: any = "hello";
console.log(m)
m = 12;
console.log(m)
m = [12, 23];
console.log(m)
m = {
code: 200,
msg: 'success',
fn(): string => {
return "你好! TS"
}
}
console.log(m.code, m.msg, m.fn)
let n: unknown = "hello";
console.log(n)
n = 12;
console.log(n)
n = [12, 23];
console.log(n)
n = {
code: 200,
msg: 'success',
fn(): string => {
return "你好! TS"
}
}
console.log(n.code, n.msg, n.fn) // 报错
never 类型: 不存在任何属于“空类型”的值,所以该类型被称为never,即不可能有这样的值。
let x:never;
x = 1 // 报错
x = 'hello' // 报错:不可能赋给它任何值,否则都会报错
react
1 react基础
npx create-react-app my-react-app
cd my-react-app; npm start; jsx
函数式组件(主要); 类组件
{} 单大括号 传值; 驼峰 className; Fragment 相当于 template; 事件 onClick
useState 状态处理; const [data, setData] = useState({ title: '标题', content: '内容'}); 状态变更,响应式; setData 需要写全属性
JSX语法,react的v-if和v-for是通过JS判断不同的状态下生成相对应得JSX。
React组件三大类:类组件、函数组件、高阶组件
类组件是React早期版本中使用的组件类型,它基于JavaScript
类实现。类组件通常用于具有复杂状态和生命周期的组件。类组件的优点是可以继承和复用,并且可以访问this关键字。
import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {
message: 'Hello, World!',
};
}
handleClick = () => {
this.setState({ message: 'Hello, React!' });
}
render() {
return (
<div>
<h1>{this.state.message}</h1>
<button onClick={this.handleClick}>Click me</button>
</div>
);
}
}
export default App;
函数式组件没有状态,没有生命周期方法
import React from 'react';
const App = ({ message }) => {
const handleClick = () => {
return <h1>{message}</h1>;
};
return (
<div>
<h1>{message}</h1>
<button onClick={handleClick}>Click me</button>
</div>
);
};
export default App;
高阶组件是一种特殊的组件类型,它接受一个组件作为参数并返回一个新的组件。高阶组件通常用于封装通用逻辑和功能,如数据处理、路由管理等。高阶组件的优点是可以提高代码复用性和模块化。
import React from 'react';
// 这是一个高阶组件,它接收一个组件作为参数,并返回一个新的组件
const withLoading = (WrappedComponent, isLoading) => {
return class extends React.Component {
render() {
const { isLoading } = this.props;
if (isLoading) {
return <div>Loading...</div>;
}
return <WrappedComponent {...this.props} />;
}
};
};
export default withLoading;
React 的函数式组件在早期版本中并不支持生命周期方法,因为它们本质上是无状态的纯函数。
React Hooks
,函数式组件也可以拥有类似于类组件中的生命周期能力了。
useEffect(() => {
// 初始化阶段 类似 componentDidMount
console.log('Component did mount');
// 初始化阶段 当 prop 或 state 改变时触发
console.log('Prop or state changed');
// 卸载阶段 返回一个清理函数,类似 componentWillUnmount
return () => {
console.log('Component will unmount');
};
}, [propName, stateName]); // 注意空数组表示只在组件挂载和卸载时运行
2 react传值
props传值(父给子传)
事件(回调函数)(子给父传)
context 上下文 createContext .Provider (祖孙组件传值)
事件总线,redux(兄弟组件或其他所有)
3 react的hooks
useState 管理组件内部的状态。
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
useContext 跨组件传递数据,避免"prop drilling"
import { createContext, useContext } from 'react';
const ThemeContext = createContext('light');
function App() {
return (
<ThemeContext.Provider value="dark">
<ThemedButton />
</ThemeContext.Provider>
);
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button style={{ backgroundColor: theme === 'dark' ? 'black' : 'white' }}>Theme Button</button>;
}
useReducer 管理复杂的状态逻辑
import { useReducer } from 'react';
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
);
}
useEffect 处理组件生命周期,例如数据获取、订阅、手动更改 DOM 等。类似 watchEffect
import { useState, useEffect } from 'react';
function FetchData() {
const [data, setData] = useState([]);
useEffect(() => {
async function fetchData() {
const response = await fetch('/api/data');
const data = await response.json();
setData(data);
}
fetchData();
}, []);
return (
<div>
<h1>Fetched Data</h1>
<ul>
{data.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
);
}
useMemo 缓存计算结果,优化性能,类似 计算属性
import { useState, useMemo } from 'react';
function ExpensiveCalculation() {
const [number, setNumber] = useState(0);
const doubledNumber = useMemo(() => {
return slowlyDoubleNumber(number);
}, [number]);
return (
<div>
<input type="number" value={number} onChange={(e) => setNumber(parseInt(e.target.value))} />
<p>Doubled number: {doubledNumber}</p>
</div>
);
}
function slowlyDoubleNumber(n) {
// 模拟一个耗时的计算
let i = 0;
while (i < 1000000000) i++;
return n * 2;
}
useCallback 缓存函数引用,优化性能
import { useState, useCallback } from 'react';
function Parent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<div>
<p>Count: {count}</p>
<ChildComponent onClick={handleClick} />
</div>
);
}
function ChildComponent({ onClick }) {
console.log('ChildComponent rendered');
return <button onClick={onClick}>Increment</button>;
}
useRef 获取 DOM 元素引用,保存可变状态
import { useRef } from 'react';
function FocusInput() {
const inputRef = useRef(null);
const handleClick = () => {
inputRef.current.focus();
};
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={handleClick}>Focus Input</button>
</div>
);
}
useLayoutEffect 处理 DOM 操作,需要同步执行
import { useLayoutEffect, useRef } from 'react';
function MeasureElement() {
const elementRef = useRef(null);
useLayoutEffect(() => {
const element = elementRef.current;
console.log('Element width:', element.offsetWidth);
}, []);
return <div ref={elementRef}>This is the element to measure</div>;
}
useImperativeHandle 暴露组件实例方法给父组件
import { forwardRef, useImperativeHandle, useRef } from 'react';
const CustomInput = forwardRef((props, ref) => {
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input type="text" ref={inputRef} />;
});
function App() {
const inputRef = useRef(null);
const handleClick = () => {
inputRef.current.focus();
};
return (
<div>
<CustomInput ref={inputRef} />
<button onClick={handleClick}>Focus Input</button>
</div>
);
}
useDebugValue 为自定义 Hooks 提供调试标签
import { useState, useDebugValue } from 'react';
function useCustomHook() {
const [state, setState] = useState(0);
useDebugValue(`Current state: ${state}`);
// 自定义 Hook 的其他逻辑
return [state, setState];
}
react 性能优化
复用组件, 同一层级, 同一类型, 同一key值
减少组件的重新render
使用 React.memo, 记忆组件
避免多层级的嵌套组件
懒加载组件
React.PureComponent 或 shouldComponentUpdate
优化 React 中的条件渲染
Suspense
react 生命周期(挂载、更新、卸载)
挂载(Mounting)
constructor: 构造函数,在组件创建之前被调用。
getDerivedStateFromProps: 在组件创建之前和更新时被调用,用于计算状态。
render: 组件渲染时被调用,必须返回一个React元素。
componentDidMount: 组件挂载到DOM后被调用。
更新(Updating)
shouldComponentUpdate: 在组件接收到新的props或state时被调用,决定是否需要重新渲染。
getDerivedStateFromProps: 同挂载阶段,用于计算状态。
render: 同挂载阶段,组件重新渲染时被调用。
componentDidUpdate: 组件更新后被调用。
卸载(Unmounting)
componentWillUnmount: 组件从DOM中移除之前被调用。
redux
Store :定义数据state 只读
action :通过action来更新数据
reducer: 纯函数来执行修改
类似vuex和pinia