Open wallleap opened 7 months ago
title: 再学 React 之函数组件 date: 2024-04-02 16:54 updated: 2024-04-02 16:54 cover: //cdn.wallleap.cn/img/pic/cover/202302ihq49n.jpg category: 技术杂谈 tags:
之前学 React 的时候,版本还是 16,虽然可以用函数组件,但是用到 state 时只能用 Class 组件。Class 组件比函数组件代码量更多,而且需要写一些冗余的代码。React 16.8 新增了 Hooks API,而且现在官方文档也推荐写函数组件。
直接定义一个函数,然后 return JSX(可以在 babel 在线网址上查看转换的 render/jsx 函数),这个函数就是一个函数组件
return
render
jsx
function App() { return <h2>这是一个函数组件</h2> } // 或者箭头函数 const App = () => <h2>这是一个函数组件</h2>
使用的时候可以调用它 App(),但推荐的方式是组件写成组件形式 <App />(JSX 中为了区分 HTML 元素和组件,规定组件以大写字母开头,并且需要闭合)
App()
<App />
在一个组件内使用另一个组件的时候,直接导入并使用
return 后最好加上 () 包裹住 JSX 元素,由于组件只能返回一个元素,如果不想用 div 包裹可以使用 fragment(简写 <></>)
()
div
fragment
<></>
import { createRoot } from "react-dom/client" const App = () => { return ( <> <h1>我是 App 组件</h1> <Child /> </> ) } const Child = () => <h2>我是 Child 组件</h2> const rootElement = document.getElementById("root") const root = createRoot(rootElement) // root.render(App()) root.render(<App />)
可以直接在子组件上写属性,然后在接收的时候以参数形式获取
const App = () => { const msg = "Hello, " return ( <> <h1>我是 App 组件</h1> <Child msg={msg} /> {/* JSX 里 JS 内容都写在 `{}` 中 */} </> ) } const Child = (props) => <h2>{props.msg}我是 Child 组件</h2>
第一个问题可以通过 useState 解决,第二个问题可以用 useEffect 等 Hooks 模拟
useState
useEffect
用法:
xxx
setXxx
if
import { useState, StrictMode } from "react" import { createRoot } from "react-dom/client" const App = () => { const [count, setCount] = useState(0) const increment = () => setCount((count) => count + 1) return ( <> <h2>{count}</h2> <button onClick={increment}>+</button> {/* 所有的属性名都是小驼峰写法,onClick、className */} </> ) } const rootElement = document.getElementById("root") const root = createRoot(rootElement) root.render( <StrictMode> <App /> </StrictMode> // 用于在开发环境下进行严格模式的检查 )
useEffect 用法:
传入两个参数
返回值为 undefined
undefined
import { useEffect, useState, StrictMode } from "react" import { createRoot } from "react-dom/client" const App = () => { const [count, setCount] = useState(0) const [childVisible, setChildVisible] = useState(false) const increment = () => setCount((count) => count + 1) useEffect(() => { console.log("依赖项为 count", count) // 每次 count 变化都会执行 }, [count]) useEffect(() => { console.log("依赖项为所有", count) // 每次渲染都会执行 }) useEffect(() => { console.log("没有依赖项", count) // 只在首次渲染时执行 }, []) return ( <> <h2>{count}</h2> <button onClick={increment}>+</button> {childVisible ? ( <button onClick={() => setChildVisible(false)}>hide</button> ) : ( <button onClick={() => setChildVisible(true)}>show</button> )} {childVisible && <Child />} </> ) } const Child = () => { const [m, setM] = useState(0) useEffect(() => { const timerId = setInterval(() => { setM((m) => m + 1) }, 1000) console.log("子组件依赖项 m", m) // m 变化执行 return () => { console.log("return 的函数中") // 组件卸载执行 clearInterval(timerId) }; }, [m]) return <div>我是子组件 {m}</div> } const rootElement = document.getElementById("root") const root = createRoot(rootElement) root.render( <StrictMode> <App /> </StrictMode> // 用于在开发环境下进行严格模式的检查 )
总结:
[]
直接使用 if-else 或其他判断语句/运算符
let content if (isLoggedIn) { content = <AdminPanel /> } else { content = <LoginForm /> } const [visible, setVisible] = useState(false) return ( <> {content} isLoggedIn ? <AdminPanel /> : <LoginForm /> visible && <Child /> </> )
JSX 中没办法直接使用 for 进行循环,可以使用数组的 map 方法或者将元素 push 到一个数组中
const products = [ { title: 'Cabbage', id: 1 }, { title: 'Garlic', id: 2 }, { title: 'Apple', id: 3 }, ] const listItems = products.map(product => <li key={product.id} // 必须有一个唯一的 key style={{ color: product.id % 2 === 0 ? "green" : "blue" }} // JSX 中 style 里面应该是一个对象 > {product.title} </li> ) return <ul>{listItems}</ul>
function MyComponent() { return ( // 在 JSX 周围 <div> {/* JSX 里面 */} <Hello // 标签里面 message="Hello, World!" // 标签里面 /> </div> ) }
title: 再学 React 之函数组件 date: 2024-04-02 16:54 updated: 2024-04-02 16:54 cover: //cdn.wallleap.cn/img/pic/cover/202302ihq49n.jpg category: 技术杂谈 tags:
前端 description: 再学 React 之函数组件
之前学 React 的时候,版本还是 16,虽然可以用函数组件,但是用到 state 时只能用 Class 组件。Class 组件比函数组件代码量更多,而且需要写一些冗余的代码。React 16.8 新增了 Hooks API,而且现在官方文档也推荐写函数组件。
创建函数组件
直接定义一个函数,然后
return
JSX(可以在 babel 在线网址上查看转换的render
/jsx
函数),这个函数就是一个函数组件使用的时候可以调用它
App()
,但推荐的方式是组件写成组件形式<App />
(JSX 中为了区分 HTML 元素和组件,规定组件以大写字母开头,并且需要闭合)在一个组件内使用另一个组件的时候,直接导入并使用
return
后最好加上()
包裹住 JSX 元素,由于组件只能返回一个元素,如果不想用div
包裹可以使用fragment
(简写<></>
)props
可以直接在子组件上写属性,然后在接收的时候以参数形式获取
转用函数组件的两个问题
第一个问题可以通过
useState
解决,第二个问题可以用useEffect
等 Hooks 模拟useState 状态钩子
用法:
xxx
setXxx
if
等条件语句中使用useEffect 副作用钩子模拟生命周期
useEffect 用法:
传入两个参数
return
一个函数,函数中可以清除之前的“副作用”(例如定时器等),在组件卸载的时候会执行该函数返回值为
undefined
总结:
[]
模拟 componentDidMountreturn
函数模拟 componentWillUnmountJSX 中技巧
条件渲染
直接使用 if-else 或其他判断语句/运算符
列表渲染
JSX 中没办法直接使用 for 进行循环,可以使用数组的 map 方法或者将元素 push 到一个数组中
JSX 注释形式