3. React條件渲染
-
- 某些情況下,姐妹的內容會根據不同的情況顯示不同的內容,或者決定是否渲染某部分內容:
- 在React中,所有的條件判斷和普通的JavaScript代碼一致;
-
- 常見的條件渲染的方式有哪些?
-
方式一: 條件判斷語句
- 適合邏輯較多的情況
-
方式二: 三元運算符
- 適合邏輯比較簡單
-
方式三: 與運算符&&
- 適合如果條件成立,渲染某一個組件;如果條件不成立,什么內容也不渲染
-
v-show的效果
- 主要是控制display屬性是否為none
-
示例代碼如下:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head> <body><div id="root"></div><script src="../lib/react.js"></script><script src="../lib/react-dom.js"></script><script src="../lib/babel.js"></script><script type="text/babel">// 1.定義App根組件class App extends React.Component {constructor () {super()this.state = {message: 'hello world',isReady: false,friend: undefined}}render () {const { isReady, friend } = this.state// 1.條件判斷方式一: 使用if進行條件判斷let showElement = nullif(isReady) {showElement = <h2>準備開始比賽吧</h2>} else {showElement = <h2>請提前做好準備!</h2>}return (<div>{ /* 1. 方式一: 根據條件給變量賦值不同的內容 */ }<div>{ showElement }</div>{ /* 2. 方式二: 三元運算符 */ }<div>{ isReady ? <button>開始戰斗!</button> : <h3> 趕緊準備 </h3> }</div>{ /* 3. 方式三: && 邏輯與運算符 */ } { /* 場景: 當某一個值, 有可能為undefined時,使用&&進行條件判斷 */ }{/* 轉成Boolean值時不顯示的 */}<div>{ friend && <div>{ friend.name + ' ' + friend.desc }</div> }</div></div>)}}// 2. 創建root并且渲染App組件const root = ReactDOM.createRoot(document.querySelector('#root'))root.render(<App/>)</script> </body> </html>
4. React列表渲染
-
- 真實開發中會從服務器請求大量的數據,數據會以列表的形式存儲:
- 比如歌曲、歌手、排行榜列表的數據;
- 比如商品、購物車、評論列表的數據;
- 比如好友消息、動態、聯系人列表的數據;
-
- 在React中沒有像Vue模板語法中的v-for指令,而是需要通過Javascript代碼的方式組織數據,轉成JSX;
- 很多從Vue轉到React的非常不習慣,認為Vue的方式更賤簡潔明了;
- 但是React中的JSX正式因為和Javascript無縫的銜接,讓他可以更加的靈活;
- React是真正可以提高我們編寫代碼能力的一種方式;
-
- 如何展示列表
- 在React中,展示列表最多的方式就是使用數組的map方法
-
- 很多時候在展示一個數組中的數據之前,需要先對他進行一些處理;
- 比如過濾掉一些內容:filter函數
- 比如截取數組中的一部分內容: slice函數
- 示例代碼如下:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.item {border: 1px solid orange;margin: 10px;padding: 0 20px;}</style> </head> <body><div id="root"></div><script src="../lib/react.js"></script><script src="../lib/react-dom.js"></script><script src="../lib/babel.js"></script><script type="text/babel">// 1.定義App根組件class App extends React.Component {constructor () {super()this.state = {students: [{ id: 111, name: 'why', score: 199 },{ id: 112, name: 'kobe', score: 98 },{ id: 113, name: 'james', score: 199 },{ id: 114, name: 'curry', score: 188 }]}}render () {const { students } = this.state// 分數大于100的學生進行展示const filterStudents = students.filter( item => item.score > 100)// 分數大于100,只展示兩個人信息// slice(start, end): [start, end)const sliceStudents = students.slice(0,2)return (<div><h2>學生列表數據</h2><div className="list">{students.filter(item => item.score> 100).slice(0, 2).map(item => {return (<div className="item"><h2>學號:{item.id}</h2> <h3>姓名:{item.name}</h3> <h1>分數:{item.score}</h1> </div> )})}</div></div>)}}// 2. 創建root并且渲染App組件const root = ReactDOM.createRoot(document.querySelector('#root'))root.render(<App/>)</script> </body> </html>
-
- 列表中的key
- 在前面的代碼中只要展示列表都會有報一個警告:
- 警告:Warning: Each child in a list should have a unique “key” prop.
- 翻譯:在一個列表中每個子元素都應該有唯一的"key"屬性
- 作用:在某些情況下(例如:插入)提高diff算法的效率
- 警告如圖:
- 添加key屬性后警告不提示:
- 這個警告是告訴需要再列表展示的jsx中添加一個key
- key主要的作用是為了提高diff算法的效率
- 具體內容后續再進行寫筆記
5. JSX的本質
-
- 實際上,jsx僅僅只是React.createElement(component, props, …children)函數的語法糖;
- 所有的jsx最終都會被轉換成React.createElement的函數調用。
-
- createElement需要傳遞三個參數:
- 參數一:type
- 當前ReactElement的類型
- 如果是標簽元素,那么就使用字符串表示
- 如果是組件元素,那么就直接使用組件的名稱
- 參數二:config
- 所有jsx中的屬性都在config中以對象的屬性和值的形式存儲
- 比如傳入className作為元素的class;
- 參數三: children
- 存放在標簽中的內容,以children數組的方式進行存儲;
- 當然,如果是多個元素呢? React內部有對他們進行處理,處理的源碼在下放
-
- babel官網查看
- 默認jsx是通過babel幫我進行語法轉換的,所以之前寫的jsx代碼都需要依賴babel。
- 可以子啊babel的官網中快速查看轉換的過程:https://babeljs.io/repl#?browsers=react
-
- 自己編寫React.createElement代碼:
- 沒有通過jsx來書寫,姐妹依然是可以正常的渲染;
- 另外,在這樣的情況下,不需要babel相關的依賴
- 所以,type="text/babel"可以刪掉
- 所以,可以刪除掉了;
- React.createElement代碼如下:
React.createElement("div",null,
“div”,
{
className: “header”
},
“Header”
),
/#PURE/ React.createElement(
“div”,
{
className: “Content”
},
/#PURE/ React.createElement(“div”, null, “Banner”),
/#PURE/ React.createElement(
“ul”,
null,
/#PURE/ React.createElement(
“li”,
null,
“\u5217\u8868\u6570\u636E1”
),
/#PURE/ React.createElement(
“li”,
null,
“\u5217\u8868\u6570\u636E2”
),
/#PURE/ React.createElement(
“li”,
null,
“\u5217\u8868\u6570\u636E3”
),
/#PURE/ React.createElement(
“li”,
null,
“\u5217\u8868\u6570\u636E4”
),
/#PURE/ React.createElement(“li”, null, “\u5217\u8868\u6570\u636E5”)
)
),
/#PURE/ React.createElement(
“div”,
{
className: “footer”
},
“Footer”
)
);
6. 虛擬DOM創建的過程
-
- 通過React.createElement做種創建出來一個ReactElement對象;
return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
-
- 這個ReactElement對象是什么作用? React為什么要創建它
- 原因是React利用ReactElement對象組成了一個
Javascript的對象樹
; - Javascript的對象樹就是
虛擬DOM(Virtual DOM)
-
- 如何查看ReactElement對象
- 可以將之前的jsx返回結果進行打印;
- 注意下面代碼中jsx的打印;
-
- 而ReactElement最終形成的樹結構就是Virtual DOM;
-
- jsx -> 虛擬DOM -> 真實DOM
- 編寫相應的jsx代碼,jsx代碼轉換完之后會變成對應的React.createElement()這樣的一個函數調用,當函數執行完之后,會形成ReactElement對象;
并且這個對象也會有嵌套,有自己的children, 它也會形成一個嵌套,形成嵌套的話它就形成就是一個虛擬DOM,而虛擬DOM的話再經過渲染最后就變成真實的DOM; jsx代碼 -> ReactElement對象 -> 真實DOM
div -> React.createElement('div', null, {}) -> ReactElement對象 -> 虛擬DOM -> 真實DOM
jsx代碼
:ReactElement對象
:真實DOM
:- 類比Vue:是template解析 -> render函數 -> h函數 -> vnode -> 虛擬dom -> 真實dom
- 類比Vue解析,Vue解析時沒有React直觀的,Vue結項相對來說麻煩一點,有各種指令
-
- 虛擬DOM的作用:
-
- 在更新數據時,沒有必要重新把整個一段代碼給重新渲染,只需要更新數據,然后重新渲染對應的數據即可
- 例如:當依賴一個數據message, 當message數據改變時,會重新調用render函數,一旦調用render函數就會形成一個新的結構, 重新執行時會在次調用createElement,就會形成一個新的虛擬DOM結構,然后還有一個舊的虛擬DOM結構,會在新舊虛擬DOM之間做一個diff算法,比較新舊虛擬DOM之間的不同,如果只是數據發生改變時,只需要更新數據就可以了。
- 總結:可以在更新的時候進行diff算法,然后決定更新那里(可以在js對象里面快速進行diff算法來決定哪些東西更新,那些東西不更新)
-
- 跨平臺,可以做跨平臺應用程序
-
- 虛擬DOM幫助我們從命令式編程轉到了聲明式編程的模式;
-
聲明式編程
-
- 虛擬DOM幫助我們從命令式編程轉到了聲明式編程的模式;
-
- React官方的說法:Virtual DOM 是一種編程理念
- 在這個理念中,UI以一種理想化或者虛擬化的方式保存在內存中,并且它是一個相對簡單的Javascript對象;
- 可以通過root.render()讓虛擬DOM和真實ODM同步起來,這個過程叫做協調(Reconciliation)
- 協調:
div -> ReactElement對象 -> 虛擬DOM -> 真實DOM
-
- 這種編程方式賦予React聲明式的API:
- 只需要告訴React希望讓UI是什么狀態;
- React來確保DOM和這些狀態是匹配的;
- 不需要直接進行DOM操作,就可以從手動更改DOM、屬性操作、事件處理中解放出來;
-