javascript
深入理解React(一)JSX与虚拟DOM
初衷
使用 React 有一段時間了, 一直想找個時間寫一個 React 的系列文章。忙里抽閑,完成了第一篇。寫這系列文章的初衷是總結這段時間的技術學習,以及給那些想學習 React 的同學們一點幫助。我會盡量以通俗易懂的語言闡述我對 React 的理解,希望能照顧到更多的新手。相信大家應該都明白一個道理,最能夠帶領你進步的,并不是比你強很多很多的大牛,而是剛好比你走得快那么一步的腳印。
為什么是React
這是2018年現代前端框架的使用情況統計,圖片來自JavaScript 如日中天,2018趨勢報告來啦!,數據僅供參考。可以看到這是個前端框架三足鼎立的時代,選擇 React 并不是因為其他框架不夠好,而是 React 本身有其獨特的魅力,吸引著開發者的聚集。就好比喜歡一個人,并不是因為其他人不好才喜歡他,而是被他獨特的魅力所吸引才產生了感情。所以對新手來說,大可不必太過糾結于框架的選擇,框架只是個幫助我們開發的工具而已。你只需要知道,React 本身足夠強大,能夠讓你在大前端的世界里走的更遠!Hello World
我們從最簡單的 Hello World 開始,進入 React 的世界,使用的是最新的 React 16版本。
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title> </head><body><div id="root"></div>// 引入react及react-dom庫<script src="https://unpkg.com/react@16/umd/react.development.js"></script><script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>// 引入babel<script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>// 在babel編譯的環境下執行<script type="text/babel">const vDom = <h1>Hello World</h1>const root = document.getElementById('root')ReactDOM.render(vDom, root)</script> </body></html> 復制代碼在使用 React 之前,我們需要先引入 React 相關的 js 庫。
- react.development.js 這是 React 的核心庫,用于構建頁面 UI
- react-dom.development.js 這是 React 的 DOM 相關操作庫,可以將你構建的 UI 渲染到瀏覽器中
除此之外,還需引入 babel 進行語法解析轉換。
我們來詳細解析下上面的 demo,其實 script 標簽中一共就寫了3句代碼,但其中包含了 React 的核心知識點——虛擬 DOM 和 JSX 。
<script type="text/babel">const vDom = <h1>Hello World</h1>const root = document.getElementById('root')ReactDOM.render(vDom, root) </script> 復制代碼JSX
JSX 是 React 的靈魂,全稱 JavaScript XML。顧名思義,它可以讓你在 JS 中使用 XML 標記的方式去直接聲明界面的 DOM,這是 React 獨有的語法糖。
請看 HelloWorld 的例子
const vDom = <h1>Hello World</h1> // 創建h1標簽,右邊千萬不能加引號 const root = document.getElementById('root') // 找到<div id="root"></div>節點 ReactDOM.render(vDom, root) // 把創建的h1標簽渲染到root節點上 復制代碼這里我們在 JS 里直接創建了一個<h1>Hello World</h1>標簽,并賦值給 vDom,這就是 JSX 語法。
如果我們將 react 庫的引入注釋掉
ReactDOM.render()這個是 react-dom 庫中的方法,用于將你創建好的 HTML 模板(虛擬 DOM 節點)插入到某個節點上,并渲染到頁面上。第一個參數是 HTML 模板,第二個參數是指定的 DOM 節點。
在上述 JSX 語法中有幾個值得注意的地方:
- 右邊的 h1 標簽千萬不能加引號。如果加上引號的,JS 引擎會將其解釋為字符串類型。其實從本質來說,<h1>Hello World</h1>這是一個對象,叫做虛擬 DOM 對象,后面會講到。
- <script> 標簽的 type 屬性為 text/babel。由于使用了 JSX 這種特殊的語法,我們不能再像往常一樣,使用<script type="text/javascript">來解析 JSX,而要借助 babel 來進行解析、轉換成 JS。
- 將 JSX 語法轉為 JavaScript 語法,這一步很消耗時間。所以現在前端項目,都會使用工作流的形式來構建,不會在 html 頁面中直接引入 react、寫 js 代碼等等。
簡單來說,就是 JSX 賦予我們在 JS 中直接創建 HTML 標簽的能力,因為 HTML 標簽實在是太弱小了。
當然我們也可以不使用 JSX 的語法創建 DOM 節點,直接使用 React 給我們提供的普通 JS 寫法,React.createElement()API 來創建。
可以看到和之前的 JSX 寫法const vDom = <h1>Hello World</h1>效果是一樣的
在使用React.createElement()這種寫法時,我們并不需要用 babel 進行解析,因為這本身就是 JS 的語法,JS 引擎可以解析。 其實本質上,JSX 就是為了簡化直接調用React.createElement() API 的一顆語法糖而已,他執行最終會被 babel 解析轉換為React.createElement()的形式,所以推薦使用 JSX 的語法來創建頁面的 UI(也就是 HTML 的一些 DOM)。JSX的優點
- 類 XML 語法結構清晰
- 增強 JS 語義
- 屏蔽 DOM 操作
- ···
我們以前在操作時,需要經過以下流程
創建節點 -> 找到插入位置 -> 插入節點,若是還有子節點,還需要繼續添加,一切都需要手動實現。
而使用 React 的 JSX 語法只需要const vDom = xxx 然后ReactDOM.render(vDom, root)就可以。
換句話說,以前都是過程式操作,你不僅知道要做什么,還需要自己手動去實現。而現在變成了聲明式操作,就好比在下命令一樣,你只需要下命令創建怎樣的 DOM 節點,然后下命令插入,中間的過程全部都由 React 框架幫你自動實現,讓開發者可以完全屏蔽 DOM 的操作。
JSX基本語法規則
- 遇到 HTML 標簽(以 < 開頭),就用 HTML 規則解析
- 遇到代碼塊{}或括號(),就用 JavaScript 規則解析
我們把 Hello World 的例子提升下
<script type="text/babel">let title = 'Hello World'const vDom = (<div><h1>{title}</h1></div>)const root = document.getElementById('root')ReactDOM.render(vDom, root) </script> 復制代碼上述代碼在執行時,當遇到<div>的左箭頭括號時,使用 HTML 的解析規則,當遇到{title}時,采用 JS 的規則解析,也就是獲取變量 title 的值。值得一提的是,如果需要創建嵌套的 HTML 結構,推薦使用()括號括起來。
虛擬DOM
- 我們在寫前端頁面時,手動操作 DOM,繁瑣又容易出錯,在大規模應用下維護起來也很困難。
- 并且每次修改 DOM,瀏覽器的 DOM 樹都需要重繪重排,效率十分低下。
- 既然 DOM 手動操作太繁瑣且效率低下,那就在每次狀態更新時重新渲染整個頁面
- 每次都重新渲染整個頁面效率十分低下,所以就加上一個虛擬 DOM
- 每次修改時,先在虛擬 DOM 上更新,最后在批量更新整個頁面,這樣頁面只需要一次大的更新,效率很高
虛擬 DOM 是在 DOM 的基礎上建立的一個抽象層,我們對 DOM 中的數據和狀態所做的任何改動,都會被自動且高效的同步到虛擬 DOM,最后再批量同步到 DOM 中。React 會在內存中維護一個虛擬 DOM 樹,當我們對這個樹進行讀或寫的時候,實際上是對虛擬 DOM 進行的。當數據變化時,React 會自動更新虛擬 DOM 樹,然后拿新的虛擬 DOM 樹和舊的虛擬 DOM 樹進行對比(當中有 DOM diff算法,這個之后再說),把不同的虛擬節點放到一個隊列里,最終在渲染時一次批量更新這些隊列中的虛擬節點到真實 DOM 中,這是對 DOM 渲染效率上的一個質的提升。
一點小結
React 以 JS 為中心,以 JSX 的獨特語法糖將"HTML"放到了 JS 里,而 JS 遠比 HTML 要強大。因此,與其增強 HTML 讓其擁有邏輯,不如增強 JS 讓其支持標簽化,這樣一來既豐富了 JS 操控領域,又提升了頁面渲染的性能。所以,你若是新手也沒關系,只要你 JS 能力足夠強,相信一定能在 React 的世界里策馬奔騰!
最后推薦幾個 React 的社區
React 官方文檔:react.docschina.org/
React China:react-china.org/
React 開源中國社區:www.oschina.net/translate/t…
我的 github 地址:github.com/FightingHao
如果有什么不懂的地方,歡迎評論,大家一起探討 React 有關的知識!
總結
以上是生活随笔為你收集整理的深入理解React(一)JSX与虚拟DOM的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM基础系列第14讲:JVM参数之GC
- 下一篇: 20181210-es6(letcons