日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

之前写的 JSX 的条件语句竟然存在那么多 Bug?

發布時間:2024/8/23 javascript 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 之前写的 JSX 的条件语句竟然存在那么多 Bug? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者 | 零一

來源 |?前端印象

今天的主題是:關于 JSX 的條件語句,你不知道3件事

一、&&隱藏大坑

在 JSX 里寫條件語句,&& 應該是用的最多的了,例如:

function?Demo?()?{//?...省略一些代碼return?(<div>{isShow?&&?<Child/>}</div>) }

這樣寫確實非常簡單易懂,但也存在隱藏的踩坑點,那就是 &&邏輯運算符的工作原理

&& 邏輯運算符工作原理: 例如 A && B ,當 A 隱式轉換后為 true 時,則返回 B;當 A 隱式轉換后為 false 時,則返回 A

舉個例子🌰:

const?A?=?0 const?B?=?1const?C?=?A?&&?B???//?0 const?D?=?B?&&?A???//?0

所以有一種場景下,我們用 && 符號做條件判斷渲染會有問題:有一個列表,當有列表數據時,展示列表里的內容;當沒有列表數據時,則什么都不展示

function?List?()?{//... }function?App?()?{const?[list,?setList]?=?useState([])useEffect(()?=>?{//?請求列表數據//?...},?[])return?(<div>{list.length?&&?<List?data={list}?/>}</div>) }

代碼看起來沒什么問題,邏輯也說得通(當 list 有具體數據時,展示 <List/> 組件),但其實是有問題的,此時頁面長這個樣:

為什么? 這就是剛才提到的 && 的工作原理了,當咱們未請求數據前,list = [] ,即 list.length = 0,那么 list.length && <List data={list} /> ?最終返回的就是 0 了,所以自然而然的 0 就出現在了頁面中

這一定不是你想要的,下面提出一些解決方案和建議吧:

  • 用三元運算符,即 list.length ? <List data={list} /> : null

  • 兩次取反,即 !!list.length && <List data={list} />

  • 直接給出具體的判斷邏輯,即 list.length > 0 && <List data={list} />

  • 當然了,如果判斷條件本來就是布爾值的話,那就可以忽略這一條了

    二、Children作判斷條件

    在某些場景下我們可能會寫一個組件來處理邏輯,例如:

    function?Wrap?(props)?{if?(props.children)?{return?(<div><p>當前內容為:</p><div>{props.children}</div></div>)}?else?{return?(<div>nothing</div>)} }function?App?()?{return?(<Wrap><div>零一</div></Wrap>) }

    這段代碼看起來也是毫無問題(當有傳遞給 <Wrap/> 組件 children 屬性時,直接展示內容;否則展示 nothing ,表示當前為空),但其實存在很多漏洞情況,例如:

    function?App?()?{return?(<Wrap>{list.map(item?=>?<span>{item}</span>)}</Wrap>) }

    假設此時變量list 為 [] ,那么 Wrap 組件中接收到的 children 則也為 [],那么 if (props.children) 的判斷結果也為 true,則頁面會這樣展示:

    這顯然不是我們想要的結果。我們想要的效果是:當接收到空數組時,也展示 nothing ,即為空

    有什么解決方案呢?

    React 提供了現成的用于處理 children的 API:

    • React.Children.map

    • React.Children.forEach

    • React.Children.count

    • React.Children.only

    • React.Children.toArray

    這里就不一一介紹每個的作用了,想要了解的可以直接去官網看:https://zh-hans.reactjs.org/docs/react-api.html#reactchildren

    我們直接挑重點說,可以直接用 React.Children.toArray 來做處理,該方法可以把 children 統一變成數組的形式

    還是用剛才的那個例子,我們改造一下看看返回了什么:

    import?{?Children?}?from?'react'function?Wrap?(props)?{//?用?Children.toArray?來處理?props.childrenif?(Children.toArray(props.children).length)?{return?(<div><p>當前內容為:</p><div>{props.children}</div></div>)}?else?{return?(<div>nothing</div>)} }function?App?()?{return?(<Wrap>{?//?返回空數組[].map(item?=>?<span>{item}</span>)}</Wrap>) }

    此時頁面展示的是:

    為什么會這樣呢?打個斷點進去看了一下 React.Children.toArray 大致都做了什么處理,這里簡單總結一下:將 children 傳過來的每個元素都放到一個數組中再返回,并會過濾掉空數組、Boolean、undefined

    所以我們剛才的例子中,空數組直接被過濾掉了。我們再來驗證一下 React.Children.toArray 的強大,舉個例子🌰

    function?App?()?{return?(<Wrap>{false?&&?<span>作者:零一</span>}{true}{?//?返回空數組[].map(item?=>?<span>{item}</span>)}{{}?.name}</Wrap>) }

    這種情況,<Wrap/> 組件接收到的 children 值應為:

    [false,true,[],undefined, ]

    那么頁面展示的是什么呢?

    是的,還是nothing,因為這四種情況的值全都被 React.Children.toArray 給過濾掉了,最終返回的值為 [] ,這也十分符合我們開發時的預期

    所以如果你真的需要把 children 作為條件判斷的依據的話,我建議是用這個方法!

    三、掛載與更新

    三元運算符在 JSX 中經常被我們拿來用于兩種不同狀態的組件切換,例如:

    import?{?Component,?useState?}?from?'react'class?Child?extends?Component?{componentDidMount()?{console.log('掛載',?this.props.name,?this.props.age);}componentDidUpdate()?{console.log('更新',?this.props.name,?this.props.age);}render?()?{const?{?name,?age?}?=?this.propsreturn?(<div><p>{name}</p><p>{age}</p></div>)} }function?App?()?{const?[year,?setYear]?=?useState('1999')return?(<div>{?year?===?'1999'???<Child?name="零一"?age={1}?/>:?<Child?name="01"?age={23}?/>}<button?onClick={()?=>?{setYear(year?===?'1999'???'2022'?:?'1999')}}>切換</button></div>) }

    看到這個代碼,你是不是覺得當變量 year 切換時,一個組件會卸載,另一個組件會掛載?但其實不是,我們來驗證一下:

    可以看到,我們在切換了變量 year 時,<Child/> 組件只掛載了一次,而不是不停地掛載、卸載。其實這是React做的處理,雖然寫了兩個 <Child/> 組件,但React只認為是一個,并直接進行更新,即上述代碼等價于:

    //?...?省略大部分代碼 function?App?()?{//?...return?(<div><Child?name={year?===?'1999'???"零一"?:?"01"}?age={year?===?'1999'???1?:?23}?/>//?...</div>) }

    這種情況需要特別注意,當你真的想寫兩次同一個組件并傳遞不同的參數時,你可以給這兩個組件賦予不同的 key ,那么React就不會認為它倆是同一個組件實例了,例如:

    function?App?()?{//?...return?(<div>{?year?===?'1999'???<Child?name="零一"?age={1}?key="0"/>:?<Child?name="01"?age={23}?key="1"/>}</div>) }

    如果本意就是不想讓兩個組件實例不停卸載和掛載,那么就不需要做額外操作了~

    往期推薦

    好難啊……一個 try-catch 問出這么多花樣

    k8s集群居然可以圖形化安裝了?

    用了HTTPS,沒想到還是被監控了

    將 k8s 制作成 3D 射擊游戲,好玩到停不下來

    點分享

    點收藏

    點點贊

    點在看

    總結

    以上是生活随笔為你收集整理的之前写的 JSX 的条件语句竟然存在那么多 Bug?的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。