Hello?React的組件化方式之React入門小案例演示
React初體驗
接下來我們通過Hello React的案例, 來體驗一下React開發(fā)模式, 以及jsx的語法
Hello React案例演練
第一步: 先引入React開發(fā)依賴
<!-- crossorigin用來解決跨域 --> <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
第二步: 這里我們編寫React的script代碼中,必須添加 type="text/babel"
,作用是可以讓babel解析jsx的語法
<script type="text/babel"> // jsx語法編寫react代碼 </script>
第三步: 創(chuàng)建元素渲染到頁面
React18之前的做法: 通過
ReactDOM.render()
函數(shù)進行渲染的, 需要傳入兩個參數(shù)參數(shù)一: 要渲染的內(nèi)容
參數(shù)二: 渲染的內(nèi)容要掛載到的HTML元素
<!-- 掛載的HTML元素 --> <div id="app"></div> <!-- crossorigin用來解決跨域 --> <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> <!-- jsx語法編寫react代碼 --> <script type="text/babel"> // React18之前的做法 ReactDOM.render(<h2>Hello World</h2>, document.querySelector("#app")) </script>
React18之后的做法: 通過
ReactDOM. createRoot()
函數(shù)進行渲染, 傳入一個參數(shù), 創(chuàng)建一個React根,之后渲染的內(nèi)容會包含在這個根中(可以有多個根, 一般是一個根)
<!-- 掛載的元素 --> <div id="app"></div> <div id="root"></div> <!-- crossorigin用來解決跨域 --> <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> <!-- jsx語法編寫react代碼 --> <script type="text/babel"> // React18之后的做法 const app = ReactDOM.createRoot(document.querySelector("#app")) const root = ReactDOM.createRoot(document.querySelector("#root")) </script>
再通過
root.render()
函數(shù)向根組件中渲染元素, 參數(shù)傳要渲染的元素
<!-- 掛載的元素 --> <div id="app"></div> <div id="root"></div> <!-- crossorigin用來解決跨域 --> <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> <!-- jsx語法編寫react代碼 --> <script type="text/babel"> // React18之后的做法 const app = ReactDOM.createRoot(document.querySelector("#app")) app.render(<h2>Hello React</h2>) const root = ReactDOM.createRoot(document.querySelector("#root")) root.render(<h2>Hello React18</h2>) </script>
Hello React案例升級
為了演練React,我們可以提出一個小的需求:
在界面顯示一個文本:Hello World
點擊下方的一個按鈕,點擊后再將文本改變?yōu)镠ello React
第一步: 將元素渲染到頁面
jsx中是通過
{}
綁定變量, 大家先對jsx語法有個體驗即可, 后面會詳細講解jsx語法
<!-- 掛載的元素 --> <div id="app"></div> <!-- crossorigin用來解決跨域 --> <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> <!-- jsx語法編寫react代碼 --> <script type="text/babel"> const app = ReactDOM.createRoot(document.querySelector("#app")) // 將文本定義成變量 let message = "Hello World" // 第二個小括號表示括號內(nèi)容是一個整體 app.render(( <div> <h2>{message}</h2> <button>改變文本</button> </div> )) </script>
第二步: 監(jiān)聽按鈕點擊, 改變message的值
監(jiān)聽按鈕點擊jsx是通過
onClick
綁定一個函數(shù), 注意C一定是大寫的
const app = ReactDOM.createRoot(document.querySelector("#app")) // 將文本定義成變量 let message = "Hello World" // 定義一個函數(shù), 處理按鈕點擊事件 function btnClick() { // 修改數(shù)據(jù) message = "Hello React" // 修改完成后需要重新渲染界面 app.render(( <div> <h2>{message}</h2> <button onClick={btnClick}>改變文本</button> </div> )) } // 第二個小括號表示括號內(nèi)容是一個整體 app.render(( <div> <h2>{message}</h2> <button onClick={btnClick}>改變文本</button> </div> ))
第三步: 簡化代碼, 上面代碼中明顯有重復代碼, 我們可以抽取到一個函數(shù)中
const app = ReactDOM.createRoot(document.querySelector("#app")) // 將文本定義成變量 let message = "Hello World" // 定義一個函數(shù), 處理按鈕點擊事件 function btnClick() { // 修改數(shù)據(jù) message = "Hello React" // 修改完成后需要重新渲染界面 rootRander() } rootRander() // 封裝一個渲染函數(shù) function rootRander() { // 第二個小括號表示括號內(nèi)容是一個整體 app.render(( <div> <h2>{message}</h2> <button onClick={btnClick}>改變文本</button> </div> )) }
Hello React的組件化
組件化的方式
Hello React這整個邏輯其實可以看做一個整體,那么我們就可以將其封裝成一個組件:
root.render()
函數(shù)的參數(shù)可以是一個HTML元素, 也可以是一個組件;所以我們可以先將之前的業(yè)務邏輯封裝到一個
組件
中,然后傳入到root.render
函數(shù)中的第一個參數(shù);
在React中,如何封裝一個組件呢?
React的組件分為兩種:
類組件
和函數(shù)式組件
這里我們暫時使用類的方式封裝組件:
定義一個類(類名大寫,組件的名稱是必須大寫的,小寫會被認為是HTML元素),繼承自
React.Component
// 類繼承自React.Component, 才是組件 class App extends React.Component{}
實現(xiàn)當前組件的render函數(shù), render當中返回的jsx內(nèi)容,就是之后React會幫助我們渲染的內(nèi)容
class App extends React.Component { // 類中render函數(shù)的返回值, 就是要渲染到頁面的內(nèi)容 render() { return ( <div> <h2>Hello World</h2> <button>改變文本</button> </div> ) } } const app = ReactDOM.createRoot(document.querySelector("#app")) app.render(<App/>)
數(shù)據(jù)依賴
組件化問題一:數(shù)據(jù)在哪里定義?
在組件中的數(shù)據(jù),我們可以分成兩類:
參與界面更新的數(shù)據(jù):當數(shù)據(jù)變量時,需要更新組件渲染的內(nèi)容;
不參與界面更新的數(shù)據(jù):當數(shù)據(jù)變量時,不需要更新將組建渲染的內(nèi)容;
參與界面更新的數(shù)據(jù)我們也可以稱之為是參與數(shù)據(jù)流
,這個數(shù)據(jù)是定義在當前對象的state
中(這個名字是固定的)
我們可以通過在類的構造器中
this.state = {定義的數(shù)據(jù)}
當我們的數(shù)據(jù)發(fā)生變化時,我們可以調(diào)用 this.setState 來更新數(shù)據(jù),并且通知React進行update操作;
在進行update操作時,就會重新調(diào)用render函數(shù),并且使用最新的數(shù)據(jù),來渲染界面
class App extends React.Component { constructor() { super() this.state = { message: "Hello World" } } // 類中render函數(shù)的返回值, 就是要渲染到頁面的內(nèi)容 render() { return ( <div> <h2>{this.state.message}</h2> <button>改變文本</button> </div> ) } } const app = ReactDOM.createRoot(document.querySelector("#app")) app.render(<App/>)
事件綁定
組件化問題二:事件綁定中的this
在類中直接定義一個函數(shù),并且將這個函數(shù)綁定到元素的onClick事件上,那么問題來了當前這個函數(shù)中的this指向的是誰呢?
默認情況下是undefined
很奇怪,居然是undefined;
因為在正常的DOM操作中,監(jiān)聽點擊,監(jiān)聽函數(shù)中的this其實是節(jié)點對象(比如說是button對象);
這次因為React并不是直接渲染成真實的DOM,我們所編寫的button只是一個語法糖,它的本質(zhì)React的Element對象;
那么在這里發(fā)生監(jiān)聽的時候,react在執(zhí)行函數(shù)時并沒有綁定this,默認情況下就是一個undefined;
我們在綁定的函數(shù)中,可能想要使用當前對象,比如執(zhí)行 this.setState 函數(shù),就必須拿到當前對象的this
我們就需要在傳入函數(shù)時,需要給這個函數(shù)直接綁定this
類似于這種寫法:
<button onClick={this.changeText.bind(this)}>改變文本</button>
class App extends React.Component { constructor() { super() this.state = { message: "Hello World" } } btnClick() { // setState內(nèi)部會做兩件事情: 1.將state中的值改掉 2.自動執(zhí)行render函數(shù)渲染頁面 this.setState({ message: "Hello React" }) } render() { return ( <div> <h2>{this.state.message}</h2> <button onClick={this.btnClick.bind(this)}>改變文本</button> </div> ) } } const app = ReactDOM.createRoot(document.querySelector("#app")) app.render(<App/>)
如果有多個按鈕, 每次都需要編寫
this.btnClick.bind(this)
是比較麻煩的, 因此React中還有另一種常見的寫法, 在constructor在提前綁定this, 這樣就可以直接使用方法這也是官方文檔在的做法
class App extends React.Component { constructor() { super() this.state = { message: "Hello World" } // 為方法提前綁定this this.btnClick = this.btnClick.bind(this) } btnClick() { this.setState({ message: "Hello React" }) } render() { return ( <div> <h2>{this.state.message}</h2> <button onClick={this.btnClick}>改變文本</button> </div> ) } } const app = ReactDOM.createRoot(document.querySelector("#app")) app.render(<App/>)
其他案例練習
電影列表展示
定義一個數(shù)組中存放電影, 再對電影列表進行展示
class App extends React.Component { constructor() { super() this.state = { movies: ["大話西游", "黑話律師", "獨行月球"] } } render() { return ( <div> <h2>電影列表</h2> <ul> <li>{this.state.movies[0]}</li> <li>{this.state.movies[1]}</li> <li>{this.state.movies[2]}</li> </ul> </div> ) } } const app = ReactDOM.createRoot(document.querySelector("#app")) app.render(<App/>)
但是顯然目前這種方法是好的, 我們最好對movies進行遍歷展示, 而遍歷的方式又有很多種, 先將下面兩種方式
方式一: 對movies數(shù)組遍歷放入一個新數(shù)組中
class App extends React.Component { constructor() { super() this.state = { movies: ["大話西游", "黑話律師", "獨行月球"] } } render() { const liEls = [] for (let item of this.state.movies) { const liEl = <li key={item}>{item}</li> liEls.push(liEl) } return ( <div> <h2>電影列表</h2> <ul> {liEls} </ul> </div> ) } } const app = ReactDOM.createRoot(document.querySelector("#app")) app.render(<App/>)
方式二: 使用map直接生成一個新數(shù)組, 直接將這個數(shù)組放入ul元素中
class App extends React.Component { constructor() { super() this.state = { movies: ["大話西游", "黑話律師", "獨行月球"] } } render() { return ( <div> <h2>電影列表</h2> <ul> {this.state.movies.map(item => <li key={item}>{item}</li>)} </ul> </div> ) } } const app = ReactDOM.createRoot(document.querySelector("#app")) app.render(<App/>)
計數(shù)器的案例
接下來再使用React做一個熟悉的計數(shù)器案例
class App extends React.Component { constructor() { super() this.state = { conter: 0 } // 為方法綁定this this.increment = this.increment.bind(this) this.decrement = this.decrement.bind(this) } increment() { this.setState({ conter: this.state.conter + 1 }) } decrement() { this.setState({ conter: this.state.conter - 1 }) } render() { return ( <div> <h2>{this.state.conter}</h2> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> </div> ) } } const app = ReactDOM.createRoot(document.querySelector("#app")) app.render(<App/>)
到此這篇關于Hello React的組件化方式-React入門小案例的文章就介紹到這了,更多相關Hello React案例內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
React超詳細分析useState與useReducer源碼
我正在處理的組件是表單的時間輸入。表單相對復雜,并且是動態(tài)生成的,根據(jù)嵌套在其他數(shù)據(jù)中的數(shù)據(jù)顯示不同的字段。我正在用useReducer管理表單的狀態(tài),到目前為止效果很好2022-11-11使用React hook實現(xiàn)remember me功能
相信大家在使用 React 寫頁面的時候都遇到過完成 Remember me 的需求吧!本文就將這個需求封裝在一個 React hook 中以供后續(xù)的使用,覺得有用的同學可以收藏起來以備不時之需,感興趣的小伙伴跟著小編一起來看看吧2024-04-04React在組件中如何監(jiān)聽redux中state狀態(tài)的改變
這篇文章主要介紹了React在組件中如何監(jiān)聽redux中state狀態(tài)的改變,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08react中的forwardRef 和memo的區(qū)別解析
forwardRef和memo是React中用于性能優(yōu)化和組件復用的兩個高階函數(shù),本文給大家介紹react中的forwardRef 和memo的區(qū)別及適用場景,感興趣的朋友跟隨小編一起看看吧2023-10-10Vite+React+TypeScript手擼TodoList的項目實踐
本文主要介紹了Vite+React+TypeScript手擼TodoList的項目實踐,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-05-05