React-快速入門

學(xué)習(xí)(React 官方中文文檔)[https://zh-hans.react.dev/]

快速入門

創(chuàng)建和嵌套組件

React 應(yīng)用程序是由 組件 組成的。一個(gè)組件是 UI(用戶界面)的一部分,它擁有自己的邏輯和外觀。組件可以小到一個(gè)按鈕,也可以大到整個(gè)頁(yè)面。

React 組件是返回標(biāo)簽的 JavaScript 函數(shù):

function MyButton() {
  return (
    <button>我是一個(gè)按鈕</button>
  )
}

至此,你已經(jīng)聲明了 MyButton,現(xiàn)在把它嵌套到另一個(gè)組件中:

export default function App() {
  return (
    <div>
      <h1>歡迎來(lái)到我的應(yīng)用</h1>
      <MyButton />
    </div>
  );
}

你可能已經(jīng)注意到 <MyButton /> 是以大寫字母開(kāi)頭的。你可以據(jù)此識(shí)別 React 組件。React 組件必須以大寫字母開(kāi)頭,而 HTML 標(biāo)簽則必須是小寫字母。

效果:


image.png

export default 關(guān)鍵字指定了文件中的主要組件


使用JSX編寫標(biāo)簽

上面所使用的標(biāo)簽語(yǔ)法被稱為 JSX。它是可選的,但大多數(shù) React 項(xiàng)目會(huì)使用 JSX,主要是它很方便。

JSX 比 HTML 更加嚴(yán)格。你必須閉合標(biāo)簽,如 <br />。你的組件也不能返回多個(gè) JSX 標(biāo)簽。你必須將它們包裹到一個(gè)共享的父級(jí)中,比如 <div>...</div> 或使用空的 <>...</> 包裹:

function AboutPage() {
  return (
    <>
      <h1>關(guān)于</h1>
      <p>你好。<br />最近怎么樣?</p>
    </>
  )
}

如果你有大量的 HTML 需要移植到 JSX 中,你可以使用 在線轉(zhuǎn)換器。

添加樣式

在 React 中,你可以使用 className 來(lái)指定一個(gè) CSS 的 class。它與 HTML 的 class 屬性的工作方式相同:

<img className="avatar" />

然后,你可以在一個(gè)單獨(dú)的 CSS 文件中為它編寫 CSS 規(guī)則:

/* 在你的 CSS 文件中修改 */
.avatar {
  border-radius: 50%;
}

React 并沒(méi)有規(guī)定你如何添加 CSS 文件。最簡(jiǎn)單的方式是使用 HTML 的 <link> 標(biāo)簽

顯示數(shù)據(jù)

JSX 會(huì)讓你把標(biāo)簽放到 JavaScript 中。而大括號(hào)會(huì)讓你 “回到” JavaScript 中,這樣你就可以從你的代碼中嵌入一些變量并展示給用戶。例如,這將顯示 user.name:

return (
  <h1>
    {user.name}
  </h1>
);

你還可以將 JSX 屬性 “轉(zhuǎn)義到 JavaScript”,但你必須使用大括號(hào) 而非 引號(hào)。例如,className="avatar" 是將 "avatar" 字符串傳遞給 className,作為 CSS 的 class。但 src={user.imageUrl} 會(huì)讀取 JavaScript 的 user.imageUrl 變量,然后將該值作為 src 屬性傳遞:

return (
  <img
    className="avatar"
    src={user.imageUrl}
  />
);

你也可以把更為復(fù)雜的表達(dá)式放入 JSX 的大括號(hào)內(nèi),例如 字符串拼接

const user = {
  name: 'Hedy Lamarr',
  imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',
  imageSize: 90,
};

export default function Profile() {
  return (
    <>
      <h1>{user.name}</h1>
      <img
        className="avatar"
        src={user.imageUrl}
        alt={'Photo of ' + user.name}
        style={{
          width: user.imageSize,
          height: user.imageSize
        }}
      />
    </>
  );
}
image.png

在上面示例中,style={{}} 并不是一個(gè)特殊的語(yǔ)法,而是 style={ } JSX 大括號(hào)內(nèi)的一個(gè)普通 {} 對(duì)象。當(dāng)你的樣式依賴于 JavaScript 變量時(shí),你可以使用 style 屬性。

條件渲染

React 沒(méi)有特殊的語(yǔ)法來(lái)編寫條件語(yǔ)句,因此你使用的就是普通的 JavaScript 代碼。例如使用 if 語(yǔ)句根據(jù)條件引入 JSX:

let content;
if (isLoggedIn) {
  content = <AdminPanel />;
} else {
  content = <LoginForm />;
}
return (
  <div>
    {content}
  </div>
);

如果你喜歡更為緊湊的代碼,可以使用 條件 ? 運(yùn)算符。與 if 不同的是,它工作于 JSX 內(nèi)部:

<div>
  {isLoggedIn ? (
    <AdminPanel />
  ) : (
    <LoginForm />
  )}
</div>

當(dāng)你不需要 else 分支時(shí),你也可以使用更簡(jiǎn)短的 邏輯 && 語(yǔ)法

<div>
  {isLoggedIn && <AdminPanel />}
</div>

所有這些方法也適用于有條件地指定屬性。如果你對(duì) JavaScript 語(yǔ)法不熟悉,你可以先使用 if...else。

渲染列表

你將依賴 JavaScript 的特性,例如 for 循環(huán)array 的 map() 函數(shù) 來(lái)渲染組件列表。
假設(shè)你有一個(gè)產(chǎn)品數(shù)組:

const products = [
  { title: 'Cabbage', id: 1 },
  { title: 'Garlic', id: 2 },
  { title: 'Apple', id: 3 },
];

在你的組件中,使用 map() 函數(shù)將這個(gè)數(shù)組轉(zhuǎn)換為 <li> 標(biāo)簽構(gòu)成的列表:

const listItems = products.map(product =>
  <li key={product.id}>
    {product.title}
  </li>
);

return (
  <ul>{listItems}</ul>
);

注意, <li> 有一個(gè) key 屬性。對(duì)于列表中的每一個(gè)元素,你都應(yīng)該傳遞一個(gè)字符串或者數(shù)字給 key,用于在其兄弟節(jié)點(diǎn)中唯一標(biāo)識(shí)該元素。通常 key 來(lái)自你的數(shù)據(jù),比如數(shù)據(jù)庫(kù)中的 ID。如果你在后續(xù)插入、刪除或重新排序這些項(xiàng)目,React 將依靠你提供的 key 來(lái)思考發(fā)生了什么。

const products = [
  { title: '卷心菜', isFruit: false, id: 1 },
  { title: '大蒜', isFruit: false, id: 2 },
  { title: '蘋果', isFruit: true, id: 3 },
];

export default function ShoppingList() {
  const listItems = products.map(product =>
    <li
      key={product.id}
      style={{
        color: product.isFruit ? 'magenta' : 'darkgreen'
      }}
    >
      {product.title}
    </li>
  );

  return (
    <ul>{listItems}</ul>
  );
}
image.png

響應(yīng)事件

你可以通過(guò)在組件中聲明 事件處理 函數(shù)來(lái)響應(yīng)事件:

function MyButton() {
  function handleClick() {
    alert('You clicked me!');
  }

  return (
    <button onClick={handleClick}>
      點(diǎn)我
    </button>
  );
}

注意,onClick={handleClick} 的結(jié)尾沒(méi)有小括號(hào)!不要 調(diào)用 事件處理函數(shù):你只需 把函數(shù)傳遞給事件 即可。當(dāng)用戶點(diǎn)擊按鈕時(shí) React 會(huì)調(diào)用你傳遞的事件處理函數(shù)。

更新界面

通常你會(huì)希望你的組件 “記住” 一些信息并展示出來(lái),比如一個(gè)按鈕被點(diǎn)擊的次數(shù)。要做到這一點(diǎn),你需要在你的組件中添加 state。

首先,從 React 引入 useState

import { useState } from 'react';

現(xiàn)在你可以在你的組件中聲明一個(gè) state 變量:

function MyButton() {
  const [count, setCount] = useState(0);
  // ...

你將從 useState 中獲得兩樣?xùn)|西:當(dāng)前的 state(count),以及用于更新它的函數(shù)(setCount)。你可以給它們起任何名字,但按照慣例會(huì)像 [something, setSomething] 這樣為它們命名。

第一次顯示按鈕時(shí),count 的值為 0,因?yàn)槟惆?0 傳給了 useState()。當(dāng)你想改變 state 時(shí),調(diào)用 setCount() 并將新的值傳遞給它。點(diǎn)擊該按鈕計(jì)數(shù)器將遞增:

function MyButton() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      Clicked {count} times
    </button>
  );
}

React 將再次調(diào)用你的組件函數(shù)。第一次 count 變成 1。接著點(diǎn)擊會(huì)變成 2。繼續(xù)點(diǎn)擊會(huì)逐步遞增。
如果你多次渲染同一個(gè)組件,每個(gè)組件都會(huì)擁有自己的 state。你可以嘗試點(diǎn)擊不同的按鈕:

import { useState } from 'react';

export default function MyApp() {
  return (
    <div>
      <h1>獨(dú)立更新的計(jì)數(shù)器</h1>
      <MyButton />
      <MyButton />
    </div>
  );
}

function MyButton() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      點(diǎn)了 {count} 次
    </button>
  );
}
image.png

注意,每個(gè)按鈕會(huì) “記住” 自己的 count,而不影響其他按鈕。

使用Hook

use 開(kāi)頭的函數(shù)被稱為 HookuseState 是 React 提供的一個(gè)內(nèi)置 Hook。你可以在 React API 參考 中找到其他內(nèi)置的 Hook。你也可以通過(guò)組合現(xiàn)有的 Hook 來(lái)編寫屬于你自己的 Hook。

Hook 比普通函數(shù)更為嚴(yán)格。你只能在你的組件(或其他 Hook)的 頂層 調(diào)用 Hook。如果你想在一個(gè)條件或循環(huán)中使用 useState,請(qǐng)?zhí)崛∫粋€(gè)新的組件并在組件內(nèi)部使用它。

組件間共享數(shù)據(jù)

在前面的示例中,每個(gè) MyButton 都有自己獨(dú)立的 count,當(dāng)每個(gè)按鈕被點(diǎn)擊時(shí),只有被點(diǎn)擊按鈕的 count 才會(huì)發(fā)生改變:


image.png

然而,你經(jīng)常需要組件 共享數(shù)據(jù)并一起更新。

為了使得 MyButton 組件顯示相同的 count 并一起更新,你需要將各個(gè)按鈕的 state “向上” 移動(dòng)到最接近包含所有按鈕的組件之中。


image.png

此刻,當(dāng)你點(diǎn)擊任何一個(gè)按鈕時(shí),MyApp 中的 count 都將改變,同時(shí)會(huì)改變 MyButton 中的兩個(gè) count

具體代碼如下:
首先,將 MyButton 的 state 上移到 MyApp 中:

export default function MyApp() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>獨(dú)立更新的計(jì)數(shù)器</h1>
      <MyButton />
      <MyButton />
    </div>
  );
}

function MyButton() {
  // ... 我們正在從這里移動(dòng)代碼...
}

接著,將 MyApp 中的點(diǎn)擊事件處理函數(shù)以及 state 一同向下傳遞到 每個(gè) MyButton 中。你可以使用 JSX 的大括號(hào)向 MyButton 傳遞信息。就像之前向 <img> 等內(nèi)置標(biāo)簽所做的那樣:

export default function MyApp() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>共同更新的計(jì)數(shù)器</h1>
      <MyButton count={count} onClick={handleClick} />
      <MyButton count={count} onClick={handleClick} />
    </div>
  );
}

使用這種方式傳遞的信息被稱作 prop。此時(shí) MyApp 組件包含了 count state 以及 handleClick 事件處理函數(shù),并將它們作為 prop 傳遞給 了每個(gè)按鈕。
最后,改變 MyButton 以 讀取 從父組件傳遞來(lái)的 prop:

function MyButton({ count, onClick }) {
  return (
    <button onClick={onClick}>
      點(diǎn)了 {count} 次
    </button>
  );
}

當(dāng)你點(diǎn)擊按鈕時(shí),onClick 處理程序會(huì)啟動(dòng)。每個(gè)按鈕的 onClick prop 會(huì)被設(shè)置為 MyApp 內(nèi)的 handleClick 函數(shù),所以函數(shù)內(nèi)的代碼會(huì)被執(zhí)行。該代碼會(huì)調(diào)用 setCount(count + 1),使得 state 變量 count 遞增。新的 count 值會(huì)被作為 prop 傳遞給每個(gè)按鈕,因此它們每次展示的都是最新的值。這被稱為“狀態(tài)提升”。通過(guò)向上移動(dòng) state,我們實(shí)現(xiàn)了在組件間共享它。

import { useState } from 'react';

export default function MyApp() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>共同更新的計(jì)數(shù)器</h1>
      <MyButton count={count} onClick={handleClick} />
      <MyButton count={count} onClick={handleClick} />
    </div>
  );
}

function MyButton({ count, onClick }) {
  return (
    <button onClick={onClick}>
      點(diǎn)了 {count} 次
    </button>
  );
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 創(chuàng)建和嵌套組件 React 應(yīng)用程序是由 組件 組成的。一個(gè)組件是 UI(用戶界面)的一部分,它擁有自己的邏輯和外...
    LK_EX閱讀 106評(píng)論 0 0
  • React 官網(wǎng)學(xué)習(xí)筆記 所有 React 組件都必須像純函數(shù)一樣保護(hù)它們的 props 不被更改 在 React...
    HeroMeikong閱讀 746評(píng)論 0 1
  • 有了上一節(jié)的鋪墊,基礎(chǔ)環(huán)境我們已經(jīng)創(chuàng)建好了,再次運(yùn)行它 在瀏覽器中打開(kāi)地址:http://localhost:51...
    碼蟻男孩閱讀 289評(píng)論 0 0
  • 本文目錄: 1.React入口 2.JSX語(yǔ)法 3.組件 4.正確使用setState 5.生命周期 6.組件復(fù)合...
    前端輝羽閱讀 1,588評(píng)論 0 20
  • 發(fā)現(xiàn)好像有些沒(méi)有過(guò)的生命周期函數(shù),還沒(méi)完全弄清楚... 一、組件的生命周期 組件的生命周期,主要分為 Mounti...
    越前君閱讀 2,282評(píng)論 0 4

友情鏈接更多精彩內(nèi)容