<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【總結(jié)】1226- 寫好 JSX 條件語句的幾個(gè)建議

          共 2954字,需瀏覽 6分鐘

           ·

          2022-02-13 01:31

          大家好,我是 ConardLi。

          很多模版語言的框架(比如Vue、Angular)都會內(nèi)置一些條件語法,比如 ng-if、v-if 等,但是在 ReactJSX 里面,沒有這樣的指令,它提供給我們更靈活的選擇,但是這種靈活也會帶來很多問題,我們今天一起來看幾個(gè)避免這些問題的建議。

          小心 0

          如果我們渲染的是一個(gè)列表,可能列表里的數(shù)據(jù)不為空的時(shí)候我們才會進(jìn)行渲染,我們可能會寫出下面的判斷代碼:

          {data.length?&&?<div>{data.map((d)?=>?d)}div>}

          但是,如果 data 數(shù)組是空的,我們會在界面上看到一個(gè) 0。

          JavaScript 中,布爾運(yùn)算符不會把它們的運(yùn)算結(jié)果轉(zhuǎn)換為布爾值,另外這和 && 的工作方式有關(guān)系,如果左邊是個(gè)假值(比如 0 就是個(gè)假值),會立刻被返回,然后 React 會將這個(gè) 0 放入 DOM 中,如果是布爾值(比如false)就不會。

          如果你要使用 && ,永遠(yuǎn)讓左側(cè)的值是個(gè) Boolean 值:

          data.length?>?0?&&?jsx

          !!data.length?&&?jsx

          Boolean(data.length)?&&?jsx

          你也可以用三元運(yùn)算符:

          {data.length???<div>{data.map((d)?=>?d)}div>?:?null}

          注意優(yōu)先級

          && 運(yùn)算符比 || 具有更高的優(yōu)先級,這就意味著你得小心處理同時(shí)包含這兩種運(yùn)算符的 jsx 語句:

          你可能會寫出下面的代碼:

          data.a?||?data.b?&&?<div?className="error"?/>

          這樣寫就錯(cuò)了,上面的代碼實(shí)際上等價(jià)于:

          data.a?||?(data.b?&&?<div?className="error"?/>)

          根據(jù)以前的經(jīng)驗(yàn),如果你的代碼里有用到 || ,就建議將條件用括號括起來:

          (data.a?||?data.b)?&&?<div?className="error"?/>

          三運(yùn)算符嵌套地獄

          三元運(yùn)算符可以幫助我們很好的切換兩個(gè) JSX,但是一旦超過兩個(gè),你的邏輯很快就會進(jìn)入嵌套地獄:

          {isEmoji
          ??????<EmojiButton?/>
          ????:?isCoupon
          ??????????<CouponButton?/>
          ????????:?isLoaded?&&?<ShareButton?/>}

          你可能想把它用 && 重構(gòu)一下,但是也會有一些重復(fù)的判斷條件:

          {isEmoji?&&??}?
          {isCoupon?&&??}?
          {!isEmoji?&&?!isCoupon?&&?isLoaded?&&??}

          這時(shí)候,回到原始的 if / else 是個(gè)不錯(cuò)的選擇,建議封裝個(gè)函數(shù):

          const?getButton?=?()?=>?{
          ????if?(isEmoji)?return?<EmojiButton?/>;
          ????if?(isCoupon)?return?<CouponButton?/>;
          ????return?isLoaded???<ShareButton?/>?:?null;
          };

          不要用 JSX 用作判斷條件

          通過 props 傳遞的 React 元素能不能用作條件判斷呢,看看下面這個(gè)例子:

          const?Wrap?=?(props)?=>?{
          ????if?(!props.children)?return?null;
          ????return?<div>{props.children}div>
          };

          最好不要這樣做,因?yàn)?props.children 可能有幾種不同的情況。

          props.children 可能是一個(gè)空數(shù)組,例如 {[].map(e =>

          )}。

          那用 children.length 來判斷?也不嚴(yán)謹(jǐn),因?yàn)?children 也可能是單個(gè)元素:

          。

          React.Children.count(props.children) 支持單個(gè)和多個(gè) children,但是,你可能會認(rèn)為 {false && 'hi'}{false && 'there'} 包含兩個(gè)個(gè)元素,而實(shí)際上不是。

          我們再來試試通過 React.Children.toArray(props.children) 刪除無效的節(jié)點(diǎn),例如 false。但對于一個(gè)空片段,仍然是正確的:<>

          所以,為了避免出錯(cuò),最好還是不要用了 ...

          重新掛載還是更新?

          使用用單獨(dú)的三元運(yùn)算符分支編寫的 JSX 感覺就像是完全獨(dú)立的代碼:

          {hasItem???<Item?id={1}?/>?:?<Item?id={2}?/>}

          你覺得 hasItem 變化時(shí)會發(fā)生啥?我的猜測是首先 卸載,然后 裝載,因?yàn)槲覍懥藘蓚€(gè)個(gè)單獨(dú)的 JSX 標(biāo)簽。

          然而,React 并不知道也不關(guān)心我寫了啥,它所看到的只是 Item 相同位置的元素,所以它依然會保留掛載的實(shí)例,然后更新 props。上面的代碼實(shí)際上等價(jià)于

          當(dāng)分支包含不同的組件時(shí),比如 {hasItem ? : },React 會重新掛載,因?yàn)?Item1 無法更新為 Item2 。

          上面的情況可能問題不大,管理好狀態(tài)就好,可能比重新裝載性能還好。

          但是,如果是非受控組件,可能問題就大了:

          {mode?===?'name'
          ??????<input?placeholder="name"?/>
          ????:?<input?placeholder="phone"?/>}

          如果 mode 屬性變化了,你會發(fā)現(xiàn)之前在 name 輸入框輸入的信息還在 ...

          通常的解決方案是使用 key,它會告訴 React 這是兩個(gè)完全不一樣的元素:

          //?remounts?on?change
          {mode?===?'name'
          ??????<input?placeholder="name"?key="name"?/>
          ????:?<input?placeholder="phone"?key="phone"?/>}

          或者,使用 && 替代三元運(yùn)算符可能會更清晰一點(diǎn):

          {mode?===?'name'?&&?"name"?/>?}?
          {mode?!==?'name'?&&?"phone"?/>?}

          相反,如果你在同一個(gè)邏輯元素上的條件 props 不太一樣,你可以將條件分支拆分為兩個(gè)單獨(dú)的 JSX 標(biāo)簽來提高可讀性:

          //?messy
          ????aria-busy={loading}
          ????onClick={loading???null?:?submit}
          >
          ????{loading???<Spinner?/>?:?'submit'}
          </Button>
          /
          /?maybe?try:
          {loading
          ??????></Button>
          ????:?submitButton>}
          //?or?even
          {loading?&&?<Button?key="submit"?aria-busy><Spinner?/>Button>
          }
          {!loading?&&?<Button?key="submit"?onClick={submit}>submitButton>
          }
          //?^^?bonus:?_move_?the?element?around?the?markup,?no?remount

          總結(jié)

          • {number && } 會把0渲染出來,可以改為 {number > 0 && }。
          • 時(shí)刻記得 || 條件周圍的括號:{(cond1 || cond2) && }
          • 三元運(yùn)算符不要擴(kuò)展到超過 2 個(gè)分支,建議使用 if / else,重構(gòu)
          • 不要使用 props.children 進(jìn)行條件判斷
          • {condition ? : } 不會重新掛載 Tag 組件,如果你想重新掛載,請使用唯一 key 或單獨(dú)的 && 分支。
          • 參考:https://thoughtspile.github.io/2022/01/17/jsx-conditionals/

          1. JavaScript 重溫系列(22篇全)
          2. ECMAScript 重溫系列(10篇全)
          3. JavaScript設(shè)計(jì)模式 重溫系列(9篇全)
          4.?正則 / 框架 / 算法等 重溫系列(16篇全)
          5.?Webpack4 入門(上)||?Webpack4 入門(下)
          6.?MobX 入門(上)?||??MobX 入門(下)
          7. 120+篇原創(chuàng)系列匯總

          回復(fù)“加群”與大佬們一起交流學(xué)習(xí)~

          瀏覽 50
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99免费观看视频 | 亚洲一级二级三级片 | 成人黄色大片在线观看 | 久久成人网豆花视频 | 日韩毛片儿。 |