iT邦幫忙

0

前端開發流- 如何用React

為什麼用React?

我當初初學網頁時剛好聽到三大框架,那時就聽到React這個詞最有感覺,所以就一直寫React到現在了,如果說現在要我改寫其他框架的話,其實我會有所排斥的,原因在於三大框架都是做一樣的事但生態系跟寫法都有所不同,我認為前端有很多技術可以更加深入去研究,沒必要為了做一樣的事而改用其他框架。

前端框架到最後只是派系的爭吵罷了,而判別框架好壞的點在於工程師架構專案的思維。如後端工程師就比較偏好Angular,因為Angular的設計思維跟後端的設計思維有點相似,而新人或是設計師比較偏好Vue,因為template寫法跟靜態的html語法很相似。React 則是前端工程為導向,React的核心思維就是元件,有人會說 React 架構很有彈性,其實這個彈性就是讓你更好與需求及設計稿搭配,所以用 React 可以讓你從元件的組合及拆分更好去歸納產品的細節功能。

可以參考用React思考

我接下來是藉由我幾年的React開發經驗,回頭看官網的文件,重新了解React的設計思維,這對我來說可以更加深入的理解前端的開發工程。

為什麼要用JSX

const element = <h1>你好,世界!</h1>;

JSX 跟原始的HTML 沒有太大的差異,最大的影響就是標籤的 attribute 改成camel-case的寫法,及可以用 { } 符號撰寫 js 在JSX裡面,就像是MVC時代的template語法一樣。

但為什麼要這樣寫?其實有寫過React一陣子後就會發現,JSX的寫法非常的糟糕,彷彿就是義大利麵的寫法。

Example:

const Calendar = () => {
...//
return 
 <tbody>
    {calendar.days.map((week, i) => {
        return (
            <tr key={i}>
                {week.map((date, i) => {
                    const isSelected = isSameDay(
                        calendar.today,
                        date.date,
                    )
                    const className = `${
                        otherMonth && 'other'
                    } ${isSelected && 'selected'}`
                    return (
                        <td className={className}>
                            {getDate(date.date)}
                        </td>
                    )
                })}
            </tr>
        )
    })}
</tbody> 
} 

這其實是React的設計所致,React的核心思維就是元件,元件的定義就是從需求及設計稿歸納而得出,一個元件可能會包含視覺跟邏輯,React的想法就是讓 css 跟 html 都當作是 js的一個變數,js 則是設計邏輯去控制視覺顯示,讓相關的邏輯跟試圖都放在一起,這樣就是為什麼要用JSX寫的原因 - 元件化設計。

可回到官網看介紹JSX

為什麼要用 Virtual Dom

Virtual dom 是前端常聽到的名詞,這也是Vue跟React應用到的技術,那為什麼要用 Virtual Dom?

React 希望網頁上的元素(Element)或是數據的變動只要功能的需求更動就好,不要多做沒必要的渲染(Render) ,如官網的範例,透過Virtual Dom render 後,React只會更動有變化的值而已。這也是為什麼 React很要求Immurable的設計,因為只要有值變動就 render,一但設計錯誤很容易遇到無限迴圈的bug。所以在設計 React時就要先想好怎麼設計,什麼資料會更動,只讓哪些地方更動。正確的render element才能發揮出 Virtual dom得效能優勢。

參考官網Rendering Element

怎麼設計Components

元件(Components)是React開發的核心重點,怎麼設計元件?怎麼抽離?
這其實是寫React最容易遇到的瓶頸,因為React專案擴張到最後會發現怎麼越寫越難維護
其實就是在設計元件上出了問題。

React的元件是由設計圖跟需求定義而成,所以從官網的用React思考的範例可以參考

https://ithelp.ithome.com.tw/upload/images/20201004/20126288xxYnUbkJ5p.png

假設我們已經得到一個需求,今天需要開發一個商品的查詢清單,我們一開始是先定義一個元件叫 FilterableProductTable這個就是最原始的元件,我們會在FilterableProductTable開始撰寫所有的邏輯及視覺。而寫到最後會發現FilterableProductTable的程式碼太多太雜了,這時又可以抽離出兩個元件出來

  • SearchBar
  • ProductTable

元件就是這樣拆離出來,但也不能先有預設想法覺得可以拆就拆,因為過度拆元件反而會讓程式碼不好維護,所以依照範例雖然ProductTable還可以拆出ProductCategoryRowProductRow但如果沒有過複雜的邏輯就不用抽離出去。而如果從設計圖的描述來看回來看React的專案會發現之間是有關連性及可閱讀性,因為React的元件是從設計圖去切割出來的。而元件的命名方便讓開發者反覆回來確認設計稿跟功能是否一致。

而元件抽離出來後,資料夾結構是否要抽離成,一個元件一個檔案的資料夾結構?這要看設計思維,通常能寫在同一頁就寫在一起,漸漸在分離出去,避免過度的巢狀結構。

https://ithelp.ithome.com.tw/upload/images/20201004/201262886Hun1NScOH.png

而Components的觀念還有 Props跟State ,Props 就是元件外傳進來的參數,State就是元件內的運算,一般我們都是從State開始做設計,在16.8後我們習慣用useStateuseEffect做元件內的邏輯。

FilterableProductTableSearchBar需要抓取input的值,用來做Filter功能。

const FilterableProductTable = () =>{
  const [input,setInput] = useState("")
  const [list,setList] = useState([])
  useEffect(()=>{
     fetchFilter(input).then(setList(data))
  },[input]) 
}

而後續抽離出 SearchBarProductTable 兩個元件這時就會變成,ProductTable會從Props接收更動的值去Filter 資料顯示出來,這時fetch 資料的邏輯就可以放到ProductTable中,而如果把這個元件放到別的元件內執行,理論上也應該能顯示出所有商品的資料。

const ProductTable = ({input}) =>{
  useEffect(()=>{
     fetchFilter(input).then(setList(data))
  },[input]) 
  return <list />
}

而React的元件設計有一個特性就是由上而下的傳值,所以由下到上的傳值是非常困難的,SearchBar的值需要傳到ProductTable中,照React特性 SearchBarProductTable是同層級的,所以不能互相傳值,於是這兩個元件之間的傳值就必須透過他們的父元件FilterableProductTable傳遞,所以SearchBarinput這個state,是寫在FilterableProductTable內。

const FilterableProductTable = () =>{
  const [input,setInput] = useState("")
  const onChangeValue = e => setInput(e.target.value)
  return  <div>
      <SearchBar {...input,onChangeValue}/>
      <Productable {...input}/>
  </div>
}

從元件的分離跟傳值中我得出兩個重點

  • 沒有必要不要拆元件,因為拆元件要想清楚什麼值是props什麼值是state
  • 整個專案的設計思維是由上到下拓展。這是隨時都要警惕得,元件的上下階層是有相對應的關係的,而這個關係是可以從需求書及設計稿推估出來。

想了解更多可以看官網的

結論

React最難的點在於元件,元件的歸納需要有一定的時間去做抽離,React最難維護的點在於,如果元件沒有拆分清楚,很容易找不到什麼值是props,或是看到一堆元件卻不知道他們可以用在哪邊。

沒事不要拆元件。


尚未有邦友留言

立即登入留言