有了上一節(jié)的鋪墊,基礎(chǔ)環(huán)境我們已經(jīng)創(chuàng)建好了,再次運(yùn)行它
cd my-react-app
npm run dev
在瀏覽器中打開地址:http://localhost:5173, 并在瀏覽器中右擊,選擇檢查菜單項(xiàng),打開控制臺(tái),如下圖所示
[圖片上傳失敗...(image-be9969-1705824628102)]
這是我們上節(jié)課操作的結(jié)果。到目前為止,你只要你跟著我一步一步的做,就行了。或許你已經(jīng)懂得并了解了一react的基礎(chǔ)結(jié)構(gòu)了,也或許你還一頭霧水,不過不用擔(dān)心,開胃菜還沒開始。
react以狀態(tài)化構(gòu)建組件的方式極大的優(yōu)化了我們的開發(fā)成本,一但掌握你就愛不釋手。
JSX
我們之前創(chuàng)建的文件都是JSX文件,但是也可以是js文件,但作為標(biāo)準(zhǔn)化的開發(fā)方案,我們建議用jsx格式的文件。但大多數(shù) React項(xiàng)目為了方便起見而使用 JSX。
JSX比HTML更嚴(yán)格。您必須關(guān)閉標(biāo)簽。您的組件也無法返回多個(gè)JSX標(biāo)簽。您必須將它們包裹在共享父母中,也就是說定義的每個(gè)組件只能返回一個(gè)標(biāo)簽的組件,但這個(gè)標(biāo)簽部可以包含多個(gè)標(biāo)簽。如:<br /> <div> ... </div> <> ... </>
function AboutPage() {
return (
<>
<h1>About</h1>
<p>Hello there.<br />How do you do?</p>
</>
);
}
注意,空標(biāo)簽<></>也是一個(gè)合法的標(biāo)簽。上面的示例表示定義了一個(gè)名為AboutPage的組件,他返回的標(biāo)簽是一個(gè)空標(biāo)簽包裹的二個(gè)其它元素標(biāo)簽。
樣式
在JSX中給組件添加樣式要注意,class要用className替代,如:
<img className="avatar" />
然后在單獨(dú)的CSS文件書寫樣式:
/* In your CSS */
.avatar {
border-radius: 50%;
}
樣式文件你直接導(dǎo)入就可以了。在組件的開頭導(dǎo)入如:
import './public.css';
顯示數(shù)據(jù)
JSX 允許您將標(biāo)記放入 JavaScript 中。大括號(hào)可讓您“逃逸”到 JavaScript 中,以便您可以從代碼中嵌入一些變量并將其顯示給用戶。例如,這將顯示:user.name。
return (
<h1>
{ user.name }
</h1>
);
您也可以從 JSX 屬性中“轉(zhuǎn)義到 JavaScript”,但您必須使用大括號(hào)而不是引號(hào)。例如,將字符串作為 CSS 類傳遞,但讀取 JavaScript 變量值,然后將該值作為屬性傳遞:
return (
<img
className="avatar"
src={user.imageUrl}
/>
);
在你的src目錄中創(chuàng)建文件:profile.jsx文件,并添加以下內(nèi)容
示例:profile.jsx
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
}}
/>
</>
);
}
創(chuàng)建一個(gè)樣式文件:styles.css
.avatar {
border-radius: 50%;
}
在你的App.jsx文件中導(dǎo)入并調(diào)用這個(gè)組件:
import './App.css'
import "./styles.css";
import Profile from './Profile'
function App() {
return (
<>
<Profile />
</>
)
}
export default App
在上面的例子中,不是一個(gè)特殊的語(yǔ)法,而是一個(gè)JSX大括號(hào)里面的常規(guī)對(duì)象。當(dāng)您的樣式依賴于 JavaScript 變量時(shí),可以使用該屬性。
條件渲染
在 React 中,編寫條件沒有特殊的語(yǔ)法。相反,您將使用與編寫常規(guī) JavaScript 代碼時(shí)相同的技術(shù)。例如,您可以使用 if 語(yǔ)句有條件地包含 JSX:
let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);
也就是說你可以把 JSX 當(dāng)作 JavaScript 的一種超集,安包含了 JavaScript 集合. 比如下面三目運(yùn)算符的應(yīng)用:
<div>
{
isLoggedIn ?
<AdminPanel /> :
<LoginForm />
}
</div>
以用諸如下面的語(yǔ)法:
<div>
{ isLoggedIn && <AdminPanel /> }
</div>
顯示列表數(shù)據(jù)
您將依靠 for循環(huán)和數(shù)組map() 函數(shù)等 JavaScript 功能來呈現(xiàn)組件列表。
例如,假設(shè)您有一系列產(chǎn)品:
const products = [
{ title: 'Cabbage', id: 1 },
{ title: 'Garlic', id: 2 },
{ title: 'Apple', id: 3 },
];
在組件內(nèi)部,使用該函數(shù)將產(chǎn)品數(shù)組轉(zhuǎn)換為項(xiàng)目數(shù)組:<li>
const products = [
{ title: 'Cabbage', isFruit: false, id: 1 },
{ title: 'Garlic', isFruit: false, id: 2 },
{ title: 'Apple', 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>
);
}
請(qǐng)注意 li 有個(gè)屬性 key , 凡是這種列表,對(duì)于列表中的每個(gè)項(xiàng)目,都應(yīng)傳遞一個(gè)字符串或數(shù)字標(biāo)識(shí),以便在其同級(jí)中唯一標(biāo)識(shí)該項(xiàng)目。這種標(biāo)識(shí)屬性為key。也就是相當(dāng)于 id 屬性。React 使用您的 key 來識(shí)別您稍后的插入、刪除或重新排序項(xiàng)目等操作。
響應(yīng)事件
我們知道在 html 的元素中都有響應(yīng)事件。在 React 中您可以通過在組件中聲明事件處理程序函數(shù)來響應(yīng)事件:
function MyButton() {
function handleClick() {
alert('你點(diǎn)擊了我');
}
return (
<button onClick={handleClick}>
點(diǎn)擊這里
</button>
);
}
請(qǐng)注意,onClick 內(nèi)的事件名稱末尾沒有括號(hào)!不要調(diào)用事件處理程序函數(shù):只需將其傳遞下來即可。當(dāng)用戶點(diǎn)擊按鈕時(shí),React 將調(diào)用你的事件處理程序。onClick={handleClick} 與 onClick={handleClick()} 是不一樣的, 前者是表示botton單擊事件由 handleClick 函數(shù)代理,而后者表示直接定義了一個(gè)匿名代理函數(shù),這個(gè)函數(shù)內(nèi)執(zhí)行了handleClick()函數(shù)。
UI顯示更新
通常,你會(huì)希望你的組件“記住”一些信息并顯示它。例如,您可能想要計(jì)算單擊按鈕的次數(shù)。為此,請(qǐng)向組件添加狀態(tài) 即 (state)。
首先,從 React 導(dǎo)入 useState:
import { useState } from 'react';
現(xiàn)在,您可以在組件中聲明一個(gè)狀態(tài)變量:
function MyButton() {
const [count, setCount] = useState(0);
// ...
您將從以下兩個(gè)方面獲得:當(dāng)前狀態(tài) count和允許您更新它的函數(shù) setCount。你可以給它們起任何名字,但慣例是寫[something, setSomething]
第一次顯示該按鈕時(shí),狀態(tài)是 count => 0。如果要更改狀態(tài),請(qǐng)調(diào)用setCount(新值)并將其傳遞給它。當(dāng)調(diào)用setCount(1) 后,會(huì)立即將更新后的值傳遞給count變量, 每當(dāng)狀態(tài)變量 count 的改變,引用這一變量的組件就會(huì)自動(dòng)更新渲染。
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
你單擊了 { count } 次
</button>
);
}
完整示例如下,我們?cè)趕rc下新建文件 buttonClickTest.jsx文件
import { useState } from 'react';
export default function ButtonClickTest() {
return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}
再次修改App.jsx文件:
import './App.css'
import "./styles.css";
// import Profile from './Profile'
import ButtonClickTest from './buttonClickTest';
function App() {
return (
<>
<ButtonClickTest />
</>
)
}
export default App
分別單擊兩個(gè)按鈕,你會(huì)發(fā)現(xiàn)結(jié)果符合預(yù)期。
使用Hooks
很多人把Hooks直接翻譯成鉤子,實(shí)在是不貼切。依我看這里把它翻譯成紐帶現(xiàn)合適。react提供了很多Hook, 上面useState就是一個(gè)hook。其它常用的我后面都會(huì)講到。其作用就是讓各個(gè)組件之前如何共享數(shù)據(jù)和更新數(shù)據(jù)。
以上面的示例為例,兩個(gè)按鈕的點(diǎn)擊互不影響,一個(gè)按鈕點(diǎn)擊次數(shù)的變化不會(huì)影響到另一個(gè)按鈕的點(diǎn)擊次數(shù)?,F(xiàn)在我們來改一改,如何讓這兩個(gè)的按鈕的點(diǎn)擊數(shù)據(jù)實(shí)現(xiàn)共享呢。下面的示例說明了一切:
export default function ButtonClickTest() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
我們看到上面的 我們調(diào)用 MyButton 組件時(shí)寫法上有些變化,我們給組件里傳了兩個(gè)參數(shù) count 和 onClick ,明確的告訴組件使用統(tǒng)一指定的參數(shù)。 但是我們?cè)诙x MyButton 組件的時(shí)候并沒有接收參數(shù)。這就需要我們把 MyButton 修改一下。其實(shí)組件都能接收一個(gè) Props 對(duì)象,這個(gè)對(duì)象是可以自定義的。修改如下:
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
你單擊了 {count} 次
</button>
);
}
如果我們的VSCode中出現(xiàn) count 和 onClick下面有紅線提示,表示vite對(duì)數(shù)據(jù)類型有個(gè)檢查,可以忽略這個(gè)提示,但如果你看它實(shí)在惡心,那我們就修改一下vite的配置,不讓它進(jìn)行安全類型檢查。
找到項(xiàng)目目錄下的 .eslintrc.cjs 文件,打開它,在rules里添加以下配置即可。
...
rules: {
...
"react/prop-types": "off",
},
好了,現(xiàn)在你應(yīng)該對(duì) React 有了最基本的了解了吧。