網(wǎng)站首頁 編程語言 正文
1. 事件處理
React 中元素也可接受、處理事件,但是在語法上有一點不同。
在React 中所有事件的命名采用的是小駝峰,而非原生 DOM 的純小寫,所有事件需要我們傳入一個函數(shù),而非字符串。
例如:
const Button = () => { const handleClick = () => { console.log('click') } return <button onClick={handleClick}>click button</button> }
當事件的回調(diào)函數(shù)比較簡單時,我們也可以簡寫箭頭匿名函數(shù),例如:
const Button = () => { return ( <button onClick={() => console.log('click')} > click button </button>) }
阻止默認行為
在React 中不能通過返回 false
來阻止默認行為,例如表單提交、a標簽跳轉(zhuǎn)。我們必須要通過顯式調(diào)用 preventDefault
函數(shù),來阻止這些默認行為。
const Link = () => { return <a onClick={(e) => e.preventDefault()} > link </a> }
合成事件
在 React 中幾乎所有的事件處理函數(shù),都是一個 (event)=>void
函數(shù),如果我們使用 typescript,可以清晰的看到每個事件對應(yīng)的函數(shù)類型,React 自身也聲明了很多的事件與事件處理函數(shù)類型,例如鼠標事件:MouseEvent<T = Element>
與 MouseEventHandler<T = Element>
,我們在使用時可以根據(jù)自己的喜歡,是定義函數(shù)類型還是定義參數(shù)類型,就像這樣:
const Link = () => { const handleClick = (e: MouseEvent) => { e.preventDefault() console.log('click') } const handleMouseEnter:MouseEventHandler = (e) => { console.log('mouse enter') } return <a onMouseEnter={handleMouseEnter} onClick={handleClick} > link </a> }
在 React 中,所有事件都是 React 根據(jù) W3C 規(guī)范定義的合成事件,所以我們完全不用擔心兼容性問題,React 事件與原生事件不完全相同。
點擊此處查看合成事件文檔
2. 柯里化
柯里化這個名稱對于 Android 開發(fā)可能有點陌生,因為我們一般使用 Java 開發(fā),因為早期的 Java 不支持函數(shù)式編程(FP),而柯里化是一個函數(shù)式編程思想。
簡而言之是將一個多參函數(shù)變成單參數(shù)函數(shù),舉個栗子:
//柯里化后的單參數(shù)函數(shù) function sumCurrying(a) { return (b) => { return (c) => { return a + b + c; }; }; } //普通的多參數(shù)函數(shù) function sumNormal(a, b, c) { return a + b + c } console.log(sumCurrying(1)(2)(3)); console.log(sumNormal(1, 2, 3));
柯里化的本質(zhì),就是高階函數(shù)的一個特性:函數(shù)的返回值可以是一個函數(shù)。
上面的例子,似乎有點脫褲子放屁,看似毫無意義。但實際工程中,柯里化是一個非常實用的小 trick。最常用在事件處理需要傳入值的場景。
我們在上面說過了,React 中的事件回調(diào)函數(shù)是有固定的函數(shù)類型的,幾乎都是 (event)=>void
函數(shù)。我們需要傳入一些參數(shù)給這個事件處理函數(shù)呢?
const List = () => { const list = [ { id: 1, name: 'tom' }, { id: 2, name: 'jerry' }, { id: 3, name: 'jack' }, { id: 4, name: 'lily' }, ] const handleClick = (id: number) => { console.log(id) } return <ul> {list.map(item => <li onClick={() => handleClick(item.id)} key={item.id} > {item.name} </li> )} </ul> }
這看起來似乎很不優(yōu)雅,我們已經(jīng)聲明了 handle 函數(shù),卻又不得不在事件處理函數(shù)中寫行內(nèi)的箭頭函數(shù),如何才能更加優(yōu)雅的處理呢?
其實很簡單,我們只需要在原本的 handle 函數(shù)中,插入一個箭頭即可,就像這樣:
//before const handleClick = (id: number) => { console.log(id) } //after const handleClick = (id: number) => (e:MouseEvent) => { console.log(id) }
然后我們的 onClick 事件回調(diào)函數(shù)就可以改成 onClick={handleClick(item.id)}
,這樣看起來是不是就更加優(yōu)雅了呢?
其實這種設(shè)計思想可以說是一說就透,只不過我現(xiàn)在告訴你,這種思想就叫做:柯里化。
柯里化的目的
你可能會問我柯里化看起來只是讓我們的代碼優(yōu)雅了一點,在目前看來似乎沒有什么本質(zhì)上的變化。
但其實柯里化幫助我們實現(xiàn)了函數(shù)的一變多,我們用一個日志輸出的函數(shù)作為例子:
//原始函數(shù) const log = (date, importance, message) => { alert(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`); } //柯里化 const logCurry = (date) => (importance) => (message) => { alert(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`); }
柯里化后,函數(shù)變成這樣調(diào)用:logCurry(new Date())("DEBUG")("some debug");
現(xiàn)在我們相當于擁有這些函數(shù):
// logNow 會是帶有固定第一個參數(shù)的日志的函數(shù) let logNow = logCurry(new Date()); // 使用它 logNow("INFO", "message"); // [HH:mm] INFO message // debugNow 會是帶有固定第一個參數(shù)與第二個參數(shù)的函數(shù) let debugNow = logNow("DEBUG"); debugNow("message"); // [HH:mm] DEBUG message
看起來只是增加了幾個箭頭,實際上我們函數(shù)的靈活性大為增加。通過固定不同的參數(shù),我們從一個函數(shù)聲明獲得了多個函數(shù)。
一個簡單的例子
const Form = () => { const [form, setForm] = React.useState({}); const update = (name) => (event) => { setForm({ ...form, [name]: event.target.value, }); } const handleSubmit = (event) => { event.preventDefault(); alert(`${JSON.stringify(form)}`); } return ( <div> <h1>柯里化表單</h1> <FormItem label="用戶名" name='username' update={update} /> <FormItem label="昵稱" name='nickname' update={update} /> <FormItem label="郵箱" name='email' update={update} /> <button onClick={handleSubmit}>提交</button> </div> ) } const FormItem = ({ label, name, update }) => { return ( <div style={{ 'display': 'flex' }}> <label>{label}</label> <input onChange={update(name)} type="text" placeholder={`請輸入${label}`} /> </div> ); };
原文鏈接:https://juejin.cn/post/7100831719263043614
相關(guān)推薦
- 2022-08-17 Python?pandas.replace的用法詳解_python
- 2023-06-20 React?DOM-diff?節(jié)點源碼解析_React
- 2022-05-27 Flutter狀態(tài)管理Bloc之定時器示例_Android
- 2022-09-25 FFmpeg源碼分析:avformat_open_input()打開媒體流
- 2022-08-30 android dialog懸浮和圓角
- 2022-10-14 MapStruct 代碼生成器
- 2022-03-17 .NET?6開發(fā)TodoList應(yīng)用實現(xiàn)結(jié)構(gòu)搭建_實用技巧
- 2022-05-23 Python學習之時間包使用教程詳解_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支