目录
一、开发环境搭建
当前主流方案是使用Vite脚手架:
bash
npm create vite@latest 项目名 --template=react-ts
二、状态
1.状态驱动
传统开发依靠JavaScript+Ajax定位DOM元素并绑定事件,依靠事件驱动页面变化。
React、Vue属于状态驱动,根据状态的变化实时更新页面,封装了事件驱动的过程,只关注页面结果。
typescript
// 其中,在JavaScript中编写的HTML在编译阶段会被编译成JavaScript:
<h1 className="title">Hello World</h1>
// 实际上会被编译成:
React.createElement('h1', {className: 'title'}, 'Hello World');
状态驱动 即根据参数的值返回不同的HTML代码块,如果要基于某个参数的状态实时更新页面必须要使用 useState(0)定义参数:函数传入初始值和格式,返回状态变量和状态更新函数。
状态更新函数不仅会更新变量,还会触发该组件的一次重新渲染。由于状态变量具有不可变性,因此状态更新函数更新变量的原理是将新的状态变量赋值给引用。
javascript
export function App() {
// 状态
const [count, setCount] = useState(0)
// 视图
return <div onClick={()=>setCount(count+1)}>{count}</div>
}
而以下方式参数变化不会引起页面变化:
typescript
export function App() {
// 状态
let count = 0
// 视图
return <div onClick={()=>count+1}>{count}</div>
}
2.列表渲染
typescript
import { useState } from 'react'
interface User {
id: string
name: string
}
export const ListDemo = () => {
const [userId, setUserId] = useState('')
const [userName, setUserName] = useState('')
const [userList, setUserList] = useState<User[]>([])
const addUser = () => {
if (!userId || !userName) return
// ...userList将旧数组数据取出。并追加一条新用户数据,用新数组更新状态变量
setUserList([...userList, { id: userId, name: userName }])
setUserId('')
setUserName('')
}
return (
<div>
<input
value={userId}
onChange={(event) => setUserId(event.target.value)}
/>
<input
value={userName}
onChange={(event) => setUserName(event.target.value)}
/>
<button onClick={addUser}>+</button>
<ul>
{userList.map((item) => (
<li}>{item.id} - {item.name}</li>
))}
</ul>
</div>
)
}
三、参数
1.组件开发
组件开发即解耦页面为多个不同功能的组件,便于复用。
组件定义规范如下:
- 组件参数 一般用接口定义,参数可以是变量、函数。
- 使用export 将子组件暴露出去,其他文件可以通过import导入。
- 组件返回值是HTML代码块,可以根据参数渲染不同内容。
typescript
import { useState } from "react"
interface HelloWorldProps{
title: string,
render?: ()=> React.ReactNode
}
export const HelloWorld = (props: HelloWorldProps) =>{
const {title, render} = props;
const [count, setCount] = useState(0);
return <div>
{title} <br/>
{count} <button onClick={()=>{setCount(count+1)}}>+</button>
{render?.()}
</div>
}
2.父组件向子组件传参
父组件通过组件属性向子组件传递参数,子组件使用函数形参捕获。
typescript
import './App.css'
import { HelloWorld } from './components/HelloWorld/index'
export function App() {
return <HelloWorld title='这是父组件向子组件传递参数' render= {()=>{return <div>这是父组件向子组件传递的函数</div>}}/>
}
typescript
import { useState } from "react"
interface HelloWorldProps{
title: string,
render?: ()=> React.ReactNode
}
export const HelloWorld = (props: HelloWorldProps) =>{
const {title, render} = props;
return <div>
{title} <br/>
{render?.()}
</div>
}
3.子组件向父组件传参
父组件通过组件属性向子组件传递由父组件编写的回调函数,子组件调用父组件的回调函数并传入参数,父组件就能通过函数体拿到子组件传入的参数。
typescript
export function App() {
const [num, setNum] = useState(0);
return <div>
<HelloWorld handle={(msg: number)=>{setNum(msg)}}/>
<div>子组件向父组件传来的值:{num}</div>
</div>
}
typescript
import { useState } from "react"
interface HelloWorldProps{
handle?: (count: number)=> void
}
export const HelloWorld = (props: HelloWorldProps) =>{
const {handle} = props
const [count, setCount] = useState(0);
return <div>
{count} <button onClick={()=>{setCount(count+1); handle?.(count+1)}}>+</button>
</div>
}
四、副作用Hooks
Hook赋予组件能使用 state 状态、生命周期的能力,将静态组件动态化。
1.useState()
useState(0)用于维护状态变量,通过状态更新函数更新变量会触发该组件的一次重新渲染:
javascript
export function App() {
// 状态
const [count, setCount] = useState(0)
// 视图
return <div onClick={()=>setCount(count+1)}>{count}</div>
}
2.useEffect()
useEffect()用于监听状态变量的变化,当状态变量发生变化时执行函数体:
typescript
import './App.css'
import { useEffect, useState } from 'react'
export function App() {
// 状态
const [count, setCount] = useState(0)
//副作用
useEffect(()=>{
console.log({count})
}, [count])
// 视图
return <div onClick={()=>setCount(count+1)}>{count}</div>
}
useEffect(()=>{},[prop]),状态变量发生变化时执行useEffect(()=>{}),组件发生变化后执行useEffect(()=>{},[]),仅组件挂载阶段执行
3.useRef()
useRef()用于获取DOM和缓存变量。
typescript
import './App.css'
import { useRef } from 'react'
export function App() {
// div对象
const divRef = useRef<HTMLDivElement>(null)
return <div ref={divRef}></div>
}
4.useActionState()
useActionState()用来获取表单提交状态和返回值。
typescript
import { useActionState } from "react"
export const FormDemo = () => {
const handleSubmit = async (formData: FormData) => {
const name = formData.get("name")
console.log({name})
await api.post("/user", {name})
return {}
}
const [state, actions, pending] = useActionState(handleSubmit, null)
console.log("当前提交状态和返回值", state)
return (
<form action={actions}>
<input type="text" name="name" />
<button type="submit">提交</button>
</form>
)
}