全棧網頁開發學習筆記—Part1 React入門—a.React簡介

旭日東歌發表於2020-12-18

React 簡介

目錄

Component

JSX

Multiple components

props: passing data to components

Some note


建立一個React應用最簡單的方式是使用一個叫做create-react-app 的工具。 建立一個名為 part1 的應用,並進入到它的目錄。

$ npx create-react-app part1
$ cd part1

用如下命令就可以讓應用執行起來了

$ npm start

預設情況下,應用在本地localhost,3000埠執行,地址為 http://localhost:3000

開啟瀏覽器控制檯。 還可以開啟一個文字編輯器,這樣你就可以同時在螢幕上檢視程式碼和網頁了:

fullstack content

應用的程式碼位於src 資料夾中。 讓我們簡化一下預設程式碼,將檔案index.js 的內容改成:

import React from 'react'
import ReactDOM from 'react-dom'

const App = () => (
  <div>
    <p>Hello world</p>
  </div>
)

ReactDOM.render(<App />, document.getElementById('root'))

 

Component

【元件】

檔案index.js 定義了一個 React-元件component ,命名為App,最後一行程式碼為:

ReactDOM.render(<App />, document.getElementById('root'))

這是將其內容渲染到div 元素中,其 id 值為 'root',該元素在檔案public/index.html中定義。

預設情況下,檔案 public/index.html 並沒有什麼能夠展示在瀏覽器的HTML標籤內容。 在用 React 開發時,需要渲染的內容通常需要定義為 React 元件。

定義元件的程式碼:

const App = () => (
  <div>
    <p>Hello world</p>
  </div>
)

該元件將被渲染為div-標籤,div中又包含一個p-標籤,p標籤包含的文字為Hello world 。

嚴格來說,這個元件被定義成了一個 JavaScript 函式。如下所示,這是一個不接收任何引數的函式 :

() => (
  <div>
    <p>Hello world</p>
  </div>
)

然後該函式被賦給一個 const 修飾的變數 App:

const App = ...

由於這個函式只包含一個表示式,所以我們使用了簡寫,不簡寫的話是如下這段程式碼:

const App = () => {
  return (
    <div>
      <p>Hello world</p>
    </div>
  )
}

換句話說,這個函式返回了表示式的值。

定義元件的函式中可以包含任何型別的 JavaScript 程式碼。按如下修改的元件,可以觀察控制檯中的輸出:

const App = () => {
  console.log('Hello from component')
  return (
    <div>
      <p>Hello world</p>
    </div>
  )
}

還可以在元件內部渲染動態內容,對元件修改如下:

const App = () => {
  const now = new Date()
  const a = 10
  const b = 20

  return (
    <div>
      <p>Hello world, it is {now.toString()}</p>
      <p>
        {a} plus {b} is {a + b}
      </p>
    </div>
  )
}

大括號中的任何程式碼都會被計算,並且計算的結果將嵌入到HTML中,嵌入的位置就是 HTML 中定義的位置。

 

JSX

看起來 React 元件返回的是 HTML 標籤,但實際並不是這樣。 React 元件的佈局大部分是使用JSX編寫的, JSX 其實是在用一種特殊的方法寫 JavaScript 。 在底層,React 元件實際上返回的 JSX 會被編譯成 JavaScript。

編譯後,應用如下所示:

import React from 'react'
import ReactDOM from 'react-dom'

const App = () => {
  const now = new Date()
  const a = 10
  const b = 20
  return React.createElement(
    'div',
    null,
    React.createElement(
      'p', null, 'Hello world, it is ', now.toString()
    ),
    React.createElement(
      'p', null, a, ' plus ', b, ' is ', a + b
    )
  )
}

ReactDOM.render(
  React.createElement(App, null),
  document.getElementById('root')
)

編譯是由Babel處理的。 使用 create-react-app 建立的專案會配置為自動編譯。

JSX 與 HTML區別在於,通過在大括號中編寫一些 JavaScript,可以輕鬆地嵌入一些動態內容。 JSX 的思想與許多模板語言非常相似,就如在 Java Spring 中使用的 Thymeleaf(是一種伺服器模板語言)。

JSX 是一種“類XML”語言,這意味著每個標籤都需要關閉。 例如,換行符是一個空元素,在 HTML 中可以這樣寫:

<br>

但是在寫 JSX 時,標籤需要如下關閉:

<br />

 

Multiple components

【多元件】

按照如下方式修改應用:

const Hello = () => {  return (    <div>      <p>Hello world</p>    </div>  )}
const App = () => {
  return (
    <div>
      <h1>Greetings</h1>
      <Hello /> 
      </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

這裡定義了一個新的元件Hello,並在元件App 中引用了它。一個元件可以重用:

const App = () => {
  return (
    <div>
      <h1>Greetings</h1>
      <Hello />
      <Hello />      
      <Hello />    
      </div>
  )
}

使用 React 編寫元件,通過組合元件,甚至可以使相當複雜的應用保持很好的可維護性。React 的核心理念,就是將許多定製化的、可重用的元件組合成應用。

還有一個約定,就是應用的元件樹頂部都要有一個root 元件 叫做App。 

 

props: passing data to components

【props:向元件傳遞資料】

使用所謂的props,可以將資料傳遞給元件。

按照如下方式修改元件Hello

const Hello = (props) => {  return (
    <div>
      <p>Hello {props.name}</p>
      </div>
  )
}

現在定義元件的函式有一個引數props。 作為引數,它接收了一個物件,該物件具有元件中所定義的、用於定義user的所有“屬性”所對應的欄位。

props 按如下定義:

const App = () => {
  return (
    <div>
      <h1>Greetings</h1>
      <Hello name="George" />  
     <Hello name="Daisy" />  
     </div>
  )
}

可以有任意數量的props ,它們的值可以是“硬編碼的”字串,也可以是 JavaScript 表示式的結果。 如果props的值是通過 JavaScript 表示式實現的,那麼它必須用花括號括起來。

修改一下程式碼,使元件Hello 使用兩個props:

const Hello = (props) => {
  return (
    <div>
      <p>
        Hello {props.name}, you are {props.age} years old      
      </p>
    </div>
  )
}

const App = () => {
  const name = 'Peter'  const age = 10
  return (
    <div>
      <h1>Greetings</h1>
      <Hello name="Maya" age={26 + 10} />
      <Hello name={name} age={age} />
    </div>
  )
}

上面App 元件傳遞的props有變數的值、求和表示式的計算結果和一個常規字串。

 

Some note

【一些注意事項】

儘管React 可以生成非常清晰的錯誤訊息,也應該,在一開始的時候,每次前進一小步,並確保每一個修改都能按照預期的方式工作。

控制檯應該始終開著 。 如果瀏覽器報錯,應該試著理解錯誤的原因,例如,回退到之前的工作狀態:

fullstack content

在 React 的程式碼中編寫 console.log() 命令(列印到控制檯)是是提倡的。

React 元件名稱必須大寫。 如果像如下這麼定義:

const footer = () => {
  return (
    <div>
      <a href="https://github.com/mluukkai">mluukkai</a>
      greeting app created by <a href="https://github.com/mluukkai">mluukkai</a>
    </div>
  )
}

然後像如下這樣使用它

const App = () => {
  return (
    <div>
      <h1>Greetings</h1>
      <Hello name="Maya" age={26 + 10} />
      <footer />    </div>
  )
}

頁面是不會顯示 Footer 元件中定義的內容,React 只會建立一個空的Footer 元素。 只有將元件名稱的第一個字母更改為大寫字母, React 才會建立在 Footer 元件中定義的div-元素,並將該元素渲染在頁面上。

注意 React 元件的內容(通常)需要包含 一個根元素 。 例如,如果嘗試定義App元件而不使用最外面的div-元素:

const App = () => {
  return (
    <h1>Greetings</h1>
    <Hello name="Maya" age={26 + 10} />
    <Footer />
  )
}

結果會得到一個錯誤資訊。

fullstack content

但使用根元素並也不是唯一可行的選擇,通過建立元件陣列 也是一個有效的解決方案:

const App = () => {
  return [
    <h1>Greetings</h1>,
    <Hello name="Maya" age={26 + 10} />,
    <Footer />
  ]
}

但是,在定義應用的根元件時,陣列這種方案並不明智,而且會使程式碼看起來有點難看。

由於根元素是必須的,所以在 Dom 樹中會有“額外的” div 元素。 這可以通過使用fragments來避免,即用一個空元素來包裝元件的返回內容:

const App = () => {
  const name = 'Peter'
  const age = 10

  return (
    <>
      <h1>Greetings</h1>
      <Hello name="Maya" age={26 + 10} />
      <Hello name={name} age={age} />
      <Footer />
    </>
  )
}

現在它已經成功地編譯了,React 生成的 DOM 不再包含額外的 div-元素了。

相關文章