> Udemy課程:[Modern React with Redux [2023 Update]](https://www.udemy.com/course/react-redux/) `20230716Sun.` ## 2-10. Showing Basic Content 注意!當我們的project在瀏覽器開始執行後,`index.js`這個檔案會是第一個被執行的!(i.e.`index.js`即程式的進入點) 所以我們將在`index.js`這個檔案中產生一些component並顯示到網頁上。大致上會有5個步驟: <div style="border: black 1px solid; padding: 5px 5px; margin: 15px 0px"> <h3 style="margin: 0">step1. Import React and ReactDOM libraries</h3> </div> > 參考資料: > 1. [[筆記] Why React?](https://medium.com/%E9%BA%A5%E5%85%8B%E7%9A%84%E5%8D%8A%E8%B7%AF%E5%87%BA%E5%AE%B6%E7%AD%86%E8%A8%98/%E7%AD%86%E8%A8%98-why-react-424f2abaf9a2) > 2. [Virtual DOM | 為了瞭解原理,那就來實作一個簡易 Virtual DOM 吧!](https://medium.com/%E6%89%8B%E5%AF%AB%E7%AD%86%E8%A8%98/build-a-simple-virtual-dom-5cf12ccf379f) > 3. [從react和react-dom的關係開始](https://segmentfault.com/a/1190000037534946) > 4. [diff 算法深入一下?](https://zhuanlan.zhihu.com/p/401340016) keywords: React、ReactDOM、Virtual DOM、diff algo 先引入React跟ReactDOM這兩個函式庫。 ```javascript! import React from 'react'; import ReactDOM from 'react-dom/client'; ``` 可能會感到疑惑,為什麼這裡需要引入兩種函式庫?其實兩者都有各自負責的事情。 #### React Library that defines what a component is and how multiple component work together. React library負責描述特性,提供React API。類組件、函數組件、hooks、contexts、refs...這些都是React特性,而react 模塊只描述特性長什麼樣、該怎麼用,並不負責特性的具體實現。 #### ReactDOM Library that knows how to get a component to show up in the browser. 負責實現特性。 react-dom、react-native 稱為渲染器,負責在不同的宿主載體上實現特性,達到與描述相對應的真實效果。比如在瀏覽器上,渲染出DOM樹、響應點擊事件等。(react-native則用於mobile之上) <div style="border: black 1px solid; padding: 5px 5px; margin: 15px 0px"> <h3 style="margin: 0">step2. Get a reference to the div with ID root</h3> </div> 我們可以從專案中的public資料夾找到`index.html`檔案,但會發現這個檔案中,除了一個擁有root id的空`div`之外,什麼都沒有了,那他又是如何顯示出東西的呢?  答案就在我們要做的第二步驟中!當我們想要顯示我們做的react appilcation時,便會去取代擁有root id的空`div`,或者直接渲染進擁有root id的空`div`裡面。 所以我們必須先抓到這個`div`,如此一來便能告訴react要顯示內容在這`div`中。 ```javascript! const el = document.getElementById('root'); ``` <div style="border: black 1px solid; padding: 5px 5px; margin: 15px 0px"> <h3 style="margin: 0">step3. Tell react to take control of the element</h3> </div> 第二步驟中,我們將抓到root id的空`div`命名為`el`。接著要利用ReactDOM Library中的createRoot特性,讓我們能顯示東西在`el`中。 ```javascript! const root = ReactDOM.createRoot(el); ``` <div style="border: black 1px solid; padding: 5px 5px; margin: 15px 0px"> <h3 style="margin: 0">step4. Create a component</h3> </div> 要記得component是一個function回傳JSX,以下範例便是創造一個名為`App`的component,而這個component會回傳的內容為:<h1>Hi there!</h1> ```javascript! function App() { return <h1>Hi there!</h1>; } ``` <div style="border: black 1px solid; padding: 5px 5px; margin: 15px 0px"> <h3 style="margin: 0">step5. Show the component on the screen</h3> </div> 最後一步驟,把component渲染到螢幕上。 ```javascript! root.render(<App />); ``` **** ## 2-11. What is JSX? > 參考資料: > 1. [How to render Jsx code in the browser](https://datacadamia.com/web/javascript/react/jsx_browser) > 2. [讓瀏覽器看懂 JSX 的新選擇 HTM](https://medium.com/itsoktomakemistakes/%E8%AE%93%E7%80%8F%E8%A6%BD%E5%99%A8%E7%9C%8B%E6%87%82-jsx-%E7%9A%84%E6%96%B0%E9%81%B8%E6%93%87-htm-fd943f74304f) JSX是一種語法,他可以讓我們的JavaScript像是在寫HTML一樣,但是前面提過,Browser無法讀懂JSX,所以我們需要先將JSX轉譯成JS code。 複習一下[第一節](https://hackmd.io/mzB3hacSThe3_YR-sybWOQ)的內容:  而轉譯的過程便可以透過Bable來達成。(一般來說都是使用Bable) <div> <img src="https://hackmd.io/_uploads/Sk20ouMc2.png"> <p style="font-size: 5px; display: flex; justify-content: center;"> 截圖自React(MRWR)2-11課程 </p> </div> 這裡我們可以透過[Bable.io](https://babeljs.io/repl#?browsers=defaults%2C%20not%20ie%2011%2C%20not%20ie_mob%2011&build=&builtIns=false&corejs=3.21&spec=false&loose=false&code_lz=Q&debug=false&forceAllTransforms=false&modules=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=env%2Creact%2Cstage-2&prettier=false&targets=&version=7.22.9&externalPlugins=&assumptions=%7B%7D),來看JSX與經過Bable轉譯後的差異。  所以總結一下,寫下`<h1>Hi there!</h1>`並不能直接顯示在browser上,他只能告訴React說這裡建立了一個element,然後我們必須使用return,React才能去使用這個component。  **** ## 2-12. Printing JavaScript Variables in JSX > 參考資料: > 1. [Writing Markup with JSX](https://react.dev/learn/writing-markup-with-jsx) > 2. [JavaScript in JSX with Curly Brace](https://react.dev/learn/javascript-in-jsx-with-curly-braces) 接下來的章節會提到如何在JSX中使用JS的變數。 這裡將建立一個名為App的component,接著我們會在JSX中寫入JS expression(運算式),如果想要使用JS的變數,我們必須在JSX中運用curly brace(花括號/大括號)把該變數包起來,便可以呈現動態的內容了! ```javascript! // 4) Create a component function App() { let message = "Bye there!"; if (Math.random() > 0.5){ message = "Hi there!"; } return <h1>{message}</h1>; } ```  但要注意的是,花括號傳入的變數不能是物件(object),否則瀏覽器會報錯。 **** ## 2-13. Shorthand JS Expressions 這個章節告訴我們如何縮短JS的運算式,先以時間為例,我們現在要在螢幕上印出目前的時間,以最基本的寫法: ```javascript! function APP(){ const date = new Date(); const time = date.toLocaleTimeString(); return <h1>{time}</h1>; } ``` 但其實我們可以直接在大括號中填入要執行的JS運算式,不一定要先利用變數: ```javascript! function APP(){ return <h1>{new Date().toLocaleTimeString()}</h1> } ``` **** ## 2-16. Typical Component Layouts 接著這個章節將提到經典的component layout,也就是一般來說大多數人會如何寫一個component? 以下為常見的component寫法:  在建立component的function之中,上方主要寫一些變數或計算等等,之後要運用於JSX中的; 而下方區塊則是我們希望這個component(元件)該如何顯示在螢幕上的內容。 在這裡可以先對於component的模式有個大致概念,之後看多了,自然也會越上手、越熟悉。 **** ## 2-17. Customizing Elements with Props 我們可以知道在html中如果要有一個讓使用者輸入數字的框框,可以這樣寫: ```htmlembedded! <input type="number"> ``` 那如果現在要寫進JSX中,要怎麼寫呢?在這裡我們會運用到一個叫做props的system。  其實就跟寫html時的概念沒兩樣,我們可以從下圖知,這個範例中一共有三種property(BTW props即property的縮寫),分別為type、min、max  但這裡有個重點!就是可以跟[2-12章節](https://hackmd.io/fxY8uO0fTpa9XBizBKTYWg?view#2-12-Printing-JavaScript-Variables-in-JSX)的概念做結合。亦即props的值,我們可以利用大括號,傳入動態的變數給props,以下為修改後的範例: ```javascript! function App(){ const inputType = "number"; const minValue = 5; return ( <input type = {inputType} min = {minValue} /> ) } ``` 總結一下,在JSX中的props,props的value若是傳入變數、數字、物件或是陣列,都必須放進大括號中,而像是字串(string)則放入(雙)引號中。  尤其可以注意到物件的部份,物件的第一個大括號是給JSX的,第二個大括號則代表物件。 再來,前面[2-12章節](https://hackmd.io/fxY8uO0fTpa9XBizBKTYWg?view#2-12-Printing-JavaScript-Variables-in-JSX)有提到「花括號傳入的變數不能是物件(object),否則瀏覽器會報錯」,但其實與此章節是有區別的:  在2-12中提到的會產生錯誤,是因為不能直接顯示出物件,但此章節我們是將物件傳入給props,把物件作為了props的值了,這樣就不會產生錯誤。 **** ## 2-18. Converting HTML to JSX ## 2-19. Applying Styling in JSX 再來這個章節將要談,如何將HTML轉換成JSX,這裡老師給出了5個步驟:  <div style="background-color: #deeba2; color: #4b570e; margin: 10px 0; padding: 10px 20px; width: fit-content; display: inline-block;"> Step 1. </div> <span style="margin: 0 10px">將prop 利用駝峰式命名</span>  <div style="background-color: #deeba2; color: #4b570e; margin: 10px 0; padding: 10px 20px; width: fit-content; display: inline-block;"> Step 2. </div> <span style="margin: 0 10px">屬性若為數字則必須使用大括號(curly braces { })</span> 在HTML中,屬性若為數字,我們會將數字當作字串傳入,所以用引號。但在JSX中屬性若為數字,則要以大括號傳入,雖然不這麼做程式仍然會運作,但是會從Browser中看到error。  <div style="background-color: #deeba2; color: #4b570e; margin: 10px 0; padding: 10px 20px; width: fit-content; display: inline-block;"> Step 3. </div> <span style="margin: 0 10px">prop的值若為boolean值(true or false)</span> prop的值若為boolean值會有特殊的寫法。 1. 若為true,則可以直接寫prop的名字即可(但依然保持駝峰式寫法),當然如果想把true放進大括號中也是沒問題的,這裡只是提供一個更精簡的寫法。 2. 若為false,則必須把false寫進大括號中  <div style="background-color: #deeba2; color: #4b570e; margin: 10px 0; padding: 10px 20px; width: fit-content; display: inline-block;"> Step 4. </div> <span style="margin: 0 10px">class改寫為className</span> 在HTML中,我們會設定一些class,而在JSX中,"class"必須改成"className"做使用。 :::danger 這裡會改為className是有原因的。因為JSX會透過Bable(之類的)轉譯成JS code,而在JS中,class為關鍵字,是有特殊語法用途的,因此在JSX裡改用"className"便是為了避免語法衝突。 :::  <div style="background-color: #deeba2; color: #4b570e; margin: 10px 0; padding: 10px 20px; width: fit-content; display: inline-block;"> Step 5. </div> <span style="margin: 0 10px">inline style在JSX中用物件來表示</span> 若我們想把CSS的樣式寫在HTML中,就是利用inline style的方式,而在JSX中,則要把inline style用物件來表達。  **** ## 2-21. Extracting Components 前面我們都是把程式寫在同一個檔案中(index.js),但是當專案越來越大、越複雜時,若仍然寫在同一個檔案中,則會非常難理解整個程式。 因此,在這個章節將提到,我們會把component拆出來單獨建立一個檔案:  從上圖可知,index.js檔案將專心import以及建立root,最後將import的component給show到螢幕上。 而component的內容將丟給別的檔案來完成,例如這裡建立了一個App.js的檔案,就是要拿來專門做component用的。 而製作component的步驟大致如下:  <div style="background-color: #deeba2; color: #4b570e; margin: 10px 0; padding: 10px 20px; width: fit-content; display: inline-block;"> Step 1. </div> <span style="margin: 0 10px">建立一個檔案</span> 一般來說建立來做component的檔案,檔案名稱都會以大寫作開頭!(但不一定要這麼做,只是多數人都會這麼做,類似不成紋的規定) <div style="background-color: #deeba2; color: #4b570e; margin: 10px 0; padding: 10px 20px; width: fit-content; display: inline-block;"> Step 2. </div> <span style="margin: 0 10px">製作component</span> component必須是一個會回傳JSX的function。 ```javascript! function App(){ retern <h1>...</h1> } ``` <div style="background-color: #deeba2; color: #4b570e; margin: 10px 0; padding: 10px 20px; width: fit-content; display: inline-block;"> Step 3. </div> <span style="margin: 0 10px">export the component</span> 製作好component之後,要在該檔案的底部export這個component。 ```javascript= export default App; ``` <div style="background-color: #deeba2; color: #4b570e; margin: 10px 0; padding: 10px 20px; width: fit-content; display: inline-block;"> Step 4. </div> <span style="margin: 0 10px">import the component</span> 第三步驟將component export了,接著第四步驟就要在其他檔案(即會用到App component的檔案,這裡以index.js為例)中import 這個component。 ```javascript= // index.js import App from "./App.js"; ``` <div style="background-color: #deeba2; color: #4b570e; margin: 10px 0; padding: 10px 20px; width: fit-content; display: inline-block;"> Step 5. </div> <span style="margin: 0 10px">使用component</span> 上個步驟我們在index.js中import了App這個component,接著我們便可以在index.js檔案中使用名為App的component。 ```javascript= <App /> ``` **** ## 2-22. Module Systems Overview 這章節會提到export跟import。 <div style="border: black 1px solid; padding: 5px 5px; margin: 15px 0px; display: flex; align-items: center; justify-content: center;"> <h3 style="margin: 0;">export、import用法</h3> </div> 首先,export有兩種方式,一種是default、一種是named。 <div style="background-color: #44ebbb; color: #4b570e; margin: 10px 0; padding: 10px 20px; width: fit-content; display: inline-block;"> 第一種 </div> <span style="margin: 0 10px">default用法</span> export用default時,當我import之後,我的名稱命名不一定要跟export一樣。以下圖為例,我在App.js檔案中export了App(用default方式),但當我在index.js中要import時,發現index.js中有變數已經叫做App了!因此這裡import的名稱就改為MyApp,才不會造成名稱重複而錯誤。  <div style="background-color: #44ebbb; color: #4b570e; margin: 10px 0; padding: 10px 20px; width: fit-content; display: inline-block;"> 第二種 </div> <span style="margin: 0 10px">named用法</span> 1. 我們可以從下圖得知,App.js檔案中,已經有export default App了,因此若我們還想再export多個變數,就需要利用named的方法做export。 2. named export方法有兩種:(下圖有示範) * 大括號 * 一條程式完成  3. 而要import named export時,則需要利用大括號(如下圖)  4. 另外要注意,import named export時,無法像default export一樣,import named export是無法重新命名的 <div style="border: black 1px solid; padding: 5px 5px; margin: 15px 0px; display: flex; align-items: center; justify-content: center;"> <h3 style="margin: 0;">import from ...</h3> </div> import後面from哪裡,不同來源會有不同寫法,例如說如果檔案室我們自己建立的(例如App.js),則import時會有"./"或"../",若我們import的東西是來自package(即一開始npm 下載的各種資源),前不會有"./"或"../"。  接著可以來理解一下,"./"與"../"兩者之間的差異: "./"用於export及import的檔案在同一個資料夾底下:  如下圖所示:  如果複雜一點,與index.js同層次的為component,所以利用"./"可以先得到component,之後在進入到下一層次,也就是我們需要的App.js(如下圖所示)  而"../"則是返回到前一層(可以理解"./"是同一層),所以以下方為例: 
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up