其他章節請看:
寫了 react 有一個半月,現在又有半個月沒寫了,感覺對其仍舊比較陌生。
本文分兩部分,首先聊一下 react 的相關概念
,然後不使用任何語法糖(包括 jsx)或可能隱藏底層技術的便利措施來構建 React 元件
。
Tip:從一項新技術的底層元素起步有利於使用者更好的長期使用它
大部分 react 應用是在 Web 平臺
上。而 React Native
和 React VR
這樣的專案則創造了 react 應用在其他平臺上執行的可能
元件是 React 中最基本單元
。
元件通常對應使用者介面的一部分,比如導航。也可以擔任資料格式化等職責。
可以將任何東西作為元件,儘管並不是所有東西作為元件都有意義。
如果將整個介面作為元件,並且沒有子元件或進一步的細分,那麼對自己並沒有什麼幫助。倘若,將介面不同部分拆解成可以組合,複用的部分,卻很有幫助。
元件具有良好的封裝性
、複用性
和組合性
。有助於為使用者提供一個更簡單的方式來思考和構建使用者介面。使用 React 構建應用就像使用積木來搭建專案,而構建應用時有取之不盡的「積木」
將 UI 分解成元件可以讓人更輕鬆的處理應用不同的部分。
元件需要一起工作,也就是說元件可以組合起來形成新的元件。元件組合
也是 React 最強大的部分之一。
如果身處一箇中大型團隊,可以將元件釋出到私有註冊中心(npm 或者其他)
React 元件還有一個方面就是生命週期方法
。當元件經過其生命週期的不同時期時(掛在、更新、解除安裝等),可以使用可預測、定義良好的方法。
React 核心庫與 react-dom 和 react-native 緊密配合,側重元件的規範和定義
。能讓開發者構建一個元件樹,該元件樹能夠被瀏覽器和其他平臺所使用。
react-dom 就是一個渲染器
。針對瀏覽器環境和伺服器端渲染。
比如我們要將元件渲染到瀏覽器,就得用到 react-dom。
React Native
庫專注於原生平臺,能夠為 ios、android 和其他平臺建立 react 應用。
React 不自帶 http
等其他前端常用工具庫。開發者可以自由的選擇對於工作最好的工具。
react 屬於 專一型
,主要關注 UI 試圖方面。
而 angular 屬於 通用型
,其內建了許多解決方案,例如 http 呼叫、路由、國際化、字串和數位格式化...
Tip:通常一些優秀的團隊會用這兩種方式。
React 的建立主要用於 Facebook 的 UI 需求。雖然大多數的 web 應用在此範圍之內,但也有一些應用不在。
React 是一種抽象,也存在抽象的代價
。React 以特定的方式構建並通過 api 向外暴露,開發者會失去對底層的可見性
。當然 React 也提供了緊急出口
,讓開發者深入較低的抽象層級,仍然可以使用 jQuery,不過需要以一種相容 React 的方式使用。
有時還需要為 React 的行事方式買單。或許會影響應用的小部分(即不太適合用 React 的方式來工作)
使用 React 時所做的權衡有助於使用者成為更好的開發者。
React 旨在將複雜的任務簡單化,把不必要的複雜性從開發者身上剝離出來。
鼓勵開發者使用宣告式
的程式設計而非命令式,也就是開發者宣告元件在不同狀態下的行為和外觀即可,React 負責渲染以及更新 UI,並將效能做到恰到好處。從而讓研發人員騰出時間思考其他方面。
驅動這些的主要技術之一就是虛擬dom
。
Tip:有關虛擬dom 的介紹可以參考 vue 快速入門-虛擬dom
虛擬 Dom 不是我們關注的重點。這正是 React 簡單
的地方:開發者被解放出來,去關注最關注的部分。
什麼使 React 成為大型團隊的寵兒?首先是簡單
,其次是非固化
。
簡單的技術讓人更容易理解和使用。
React 是一個非常輕量的庫,只關注應用的檢視。更加容易與使用者當前的技術整合,並在其他方面為使用者留下了選擇的空間。一些功能固化的框架和庫要求使用者要麼全盤接受要麼徹底不用。
簡單和非固化的特性,以及恰到好處的效能,讓它非常適合大大小小的專案。
元件可以獨立存在,也可用來建立其他元件。人們認為元件可以建立很多不同類的關係,從某種意義這是對的。
但元件更多的是以靈活的方式被使用,應該關注其獨立性
和常常不帶任何負擔
,可組合使用。所以元件只關注其父母和孩子
,兄弟關係可以不管。
建立元件關係的過程對每個團隊或專案都不盡相同,元件關係也可能會隨時間而改變,我們可以不期望一次就建立完美,也無需太過擔心,因為 React 會讓我們的 UI 迭代沒那麼困難。
首先我們將元件的框架寫好:
<body>
<div id="root">
<!-- 此元素的內容將替換為您的元件 -->
</div>
<!-- react 庫 -->
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<!-- 用於處理 Dom 的 react 包 -->
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<!-- 使用 PropTypes 進行型別檢查 -->
<script src="https://unpkg.com/[email protected]/prop-types.js"></script>
<script>
const reactElem = React.createElement(
'h1',
{title: 'i am h1'},
'Hello, world!'
)
ReactDOM.render(
reactElem,
document.getElementById('root')
);
</script>
</body>
Tip:這是一個普通的 html 頁面,直接通過 vscode 的 Live Server 外掛執行即可
執行後的網頁顯示 Hello, world!
。生成的元素結構如下:
<div id="root">
<h1 title="i am h1">Hello, world!</h1>
</div>
下面我們稍微分析一下這個頁面:
首先定義了一個 div 元素,接著引入三個包,作用如下:
react.js
,React 的核心庫,用於定義元件的規範react-dom.js
,渲染器,用於瀏覽器和伺服器端渲染,用於建立元件和管理元件prop-types.js
,傳遞給元件的資料做型別檢查接著通過 React.createElement
建立一個 react 元素。
React.createElement(
type,
[props],
[...children]
)
Tip:react 元素是什麼?
普通物件
最後使用 ReactDOM.render
將 React 元素渲染到 div#root
中。
// 在提供的 container 裡渲染一個 React 元素,並返回對該元件的參照
ReactDOM.render(element, container[, callback])
Tip:呼叫 react-dom 的 render() 方法來讓 React 將組建渲染出來,並對元件進行管理。
React 元素
是你想讓 React 渲染的東西的輕量表示。它可以表示為一個 Dom 元素,上文我們已經用其建立了一個 h1
的 dom 元素。
有必要再來分析一下 createElement()
的引數:
// 建立並返回指定型別的新 React 元素。其中的型別引數既可以是標籤名字串(如 'div' 或 'span'),也可以是 React 元件 型別 (class 元件或函陣列件),或是 React fragment 型別。
React.createElement(
type,
[props],
[...children]
)
const reactElem = React.createElement(
'h1',
{title: 'i am h1'},
'Hello, world!'
)
type
,一個 html 標籤("div"、"h1")或 React 類props
,指定 html 元素上要定義哪些屬性或元件類的範例上可以使用哪些屬性children
,還記得 React 元件是可以組合的嗎?一句話:React.createElement()
在問:
我在建立什麼?
,是 Dom 元素,是 React 元件,還是React fragment。我怎麼設定它?
它包含什麼?
假如我們需要在頁面顯示如下元素:
<div>
<h2>i am h2</h2>
<a href="www.baidu.com">go baidu</a>
<p>
<em>i am em element</em>
</p>
</div>
可以這麼寫:
const c = React.createElement
const reactElem2 = React.createElement(
'div',
{},
c('h2', {}, 'i am h2'),
c('a', {href: 'www.baidu.com'}, 'go baidu'),
c('p', {},
c('em', {}, 'i am em element')
)
)
React 是怎麼把那麼多 React.createElement
轉換成螢幕上看到的東西的?這裡得用到虛擬 dom。
虛擬 dom 和真實 dom 有著相似的結構。
為了從 React 元素中形成自己的虛擬 DOM 樹
,React 會對 React.createElement 的全部 children 屬性進行求值,並將結果傳遞給父元素。就像一個小孩反覆再問 X是什麼?
,直到理解 X 的每個細節,直到他能形成一棵完整的樹。
看看這段程式碼,我們建立了一個 React 元素並將其放入 dom 中:
<script>
const c = React.createElement
const reactElem = React.createElement(
'div',
{},
c('h2', {}, 'i am h2'),
c('a', {href: 'www.baidu.com'}, 'go baidu'),
c('p', {},
c('em', {}, 'a am em element')
)
)
ReactDOM.render(
reactElem,
document.getElementById('root')
);
</script>
如果我們需要擴充套件 reactElem 的功能、樣式以及其他UI相關?這時可以使用元件
。
元件可以將這些有效的組織在一起。
所以,要真正構建東西,不僅僅需要 React 元素,還需要元件。
React 元件就像是 React 元素,但 React 元件擁有更多特性。React 元件是幫助將 React 元素和函陣列織到一起的類
我們可以使用函數或 js 類
建立元件。
使用 es6 的 class 來定義元件。就像這樣:
class MyComponent extends React.Component {
// 必須定義 render()。否則會報錯:
// MyComponent(...): No `render` method found on the returned component instance: you may have forgotten to define `render`.
render() {
// 返回單個 React 元素或 React 元素的陣列
return reactElem
}
}
通常需要至少定義一個 render() 方法,幾乎任何向螢幕顯示內容的元件都帶有 render 方法
Tip:那些不直接顯示任何東西而是修改或增強其他元件的元件(稱高階元件),後續再討論。
我們將上面範例改成元件形式:
<script>
class MyComponent extends React.Component{
render(){
const c = React.createElement
return React.createElement(
'div',
{},
c('h2', {}, this.props.cnt1),
c('a', {href: 'www.baidu.com'}, 'go baidu'),
// class 屬性在需要改為 className
c('p', {className: this.props.aClass},
c('em', {}, this.props.cnt2)
)
)
}
}
</script>
<script>
// createElement 第一個引數可以是標籤名字串(如 'div' 或 'span'),也可以是 React 元件 型別 (class 元件或函陣列件),或是 React fragment 型別
const App = React.createElement(MyComponent, {
cnt1: 'i am h2',
aClass: 'p-class',
cnt2: 'a am em element'
})
ReactDOM.render(
App,
document.getElementById('root')
);
</script>
生成的 html 如下:
<div>
<h2>i am h2</h2>
<a href="www.baidu.com">go baidu</a>
<p class="p-class">
<em>a am em element</em>
</p>
</div>
React 中通過 this.props
就能獲取傳遞給元件的屬性。
MyComponent 中沒有初始化 props 的程式碼,既然自己沒做,那麼肯定是父類別
幫忙做了。
就像這樣:
<script>
// 父類別
class Rectangle {
constructor() {
// 子類接收的引數,這裡 arguments 都能接收到
const args = Array.from(arguments)
// args= (3) [{…}, 'b', 'c']
console.log('args=', args)
this.props = args[0]
}
}
// 子類
class Square extends Rectangle {
render(){
// name= pjl
console.log('name=', this.props.name)
}
}
let square = new Square({name: 'pjl'}, 'b', 'c')
square.render()
</script>
如果需要自己寫 constructor ,則需要手動呼叫 super()
,否則會報錯。就像這樣:
// 控制檯輸入如下程式碼,報錯
// Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
// Uncaught ReferenceError:在存取「this」或從派生建構函式返回之前,必須在派生類中呼叫超級建構函式
class A{}
class B extends A{
constructor(){
}
}
let b = new B()
Tip: 有關 super 更多介紹請看 這裡
constructor(props)
如果不初始化 state 或不進行方法系結,則不需要為 React 元件實現建構函式。通常,建構函式僅用於以下兩種情況:
類元件能使用自定義屬性。
通過元件好像能建立自定義 html 元素,而且還能做得更多。
能力越大,責任也越大,我們需要使用一些方法來驗證所使用的屬性,防止缺陷、規劃元件所使用的資料種類。
在上面範例基礎上,我們增加型別檢測:
<script>
class MyComponent extends React.Component {
...
}
// 屬性型別
MyComponent.propTypes = {
cnt1: PropTypes.number,
// 注:函數不是 function,而是 func
// 函數型別,並且必填
func: PropTypes.func.isRequired
}
// 預設值
MyComponent.defaultProps = {
cnt1: 'defaultName'
}
</script>
型別檢測生效了。控制檯報錯如下:
Warning: Failed prop type: Invalid prop `cnt1` of type `string` supplied to `MyComponent`, expected `number`
警告:失敗的屬性型別:提供給「MyComponent」的型別為「string」的屬性「cnt1」無效,應為「number」`
Warning: Failed prop type: The prop `func` is marked as required in `MyComponent`, but its value is `undefined`.
警告:失敗的屬性型別:屬性「func」在「MyComponent」中標記為必需,但其值為「undefined」。
除了控制檯發出 Warning,頁面顯示仍舊正常。
這裡其實就是按照特定規定,給 MyComponent 類增加了兩個靜態成員,用於型別檢測。我們可以自己模擬一下,請看範例:
<script>
class Rectangle {
constructor() {
this.props = arguments[0]
// 模擬型別驗證
this.validate(this.constructor)
}
validate(subClass) {
Object.keys(subClass.propTypes).forEach(key => {
const propType = subClass.propTypes[key]
const type = typeof this.props[key]
if (type !== propType) {
console.error(`Warning: ${key} 屬性 - 期待型別是 ${propType},所傳入的型別確是 ${type}`)
}
})
}
}
class Square extends Rectangle {
render() {
}
}
Square.propTypes = {
name: 'string',
age: 'number'
}
let square = new Square({ name: 18, age: 'pjl' })
square.render()
</script>
型別檢測結果如下:
// 瀏覽器控制檯輸出:
Warning: name 屬性 - 期待型別是 string,所傳入的型別確是 number
Warning: age 屬性 - 期待型別是 number,所傳入的型別確是 string
現在這麼寫有些零散,我們可以使用 static
語法來對其優化。就像這樣:
class Square extends Rectangle {
static propTypes = {
name: 'string',
age: 'number'
}
render(){}
}
Tip: 有關 static 更多介紹可以百度 mdn static
我們已經建立了一個類元件,並傳入了一些屬性,現在我們可以嘗試巢狀元件。
前面我們已經提到,元件組合
是 React 中非常強大的功能。比如一個頁面,我們可以通過元件進行拆分,單獨開發,最終卻是需要將元件組合成一個頁面,否則就不好玩了。
將上面元件拆成兩個,稍作變動,程式碼如下:
<script>
class MyComponent extends React.Component {
render() {
const c = React.createElement
return React.createElement(
'div',
{ className: 'parent-class' },
c('h2', {}, this.props.cnt1),
// 核心是:this.props.children。
this.props.children
)
}
}
class MySubComponent extends React.Component {
render() {
const c = React.createElement
return React.createElement(
'div',
{ className: 'sub-class' },
c('a', { href: 'www.baidu.com' }, 'go baidu'),
c('p', { className: this.props.aClass },
c('em', {}, this.props.cnt2)
)
)
}
}
</script>
<script>
// createElement 第一個引數可以是標籤名字串(如 'div' 或 'span'),也可以是 React 元件 型別 (class 元件或函陣列件),或是 React fragment 型別
const App = React.createElement(MyComponent, {
cnt1: 'i am h2',
},
React.createElement('p', {}, 'i am p element'),
React.createElement(MySubComponent, {
aClass: 'p-class',
cnt2: 'a am em element'
}
))
ReactDOM.render(
App,
document.getElementById('root')
);
</script>
核心是 this.props.children
,每個元件都可以獲取到 props.children
。最終渲染 html 結構如下:
<div id="root">
<div class="parent-class">
<h2>i am h2</h2>
<!-- this.props.children -->
<p>i am p element</p>
<div class="sub-class">
<a href="www.baidu.com">go baidu</a>
<p class="p-class">
<em>a am em element</em>
</p>
</div>
<!-- /this.props.children -->
</div>
</div>
現在我們已經為元件新增了 render 方法和一些 propTypes。上面範例也僅僅顯示一些靜態文案,但要建立動態元件
,遠不止這些。
React 提供了某些特殊方法,當 React 管理虛擬 dom 時,react 會按順序呼叫它們,render 方法只是其中之一。
狀態可以讓元件互動並鮮活起來。
Tip: 狀態其他特性如下:
下面我們使用一下 state,既然 state 是可變狀態,那麼我們就建立一個表單元件,裡面有一個 input,一個提交按鈕。
程式碼如下:
<script>
class MyComponent extends React.Component {
render() {
const c = React.createElement
return React.createElement(
'div',
{ className: 'parent-class' },
this.props.children
)
}
}
class MySubComponent extends React.Component {
constructor(props){
// 如果不需要使用 this.props,則可以是 super()
super(props)
// 在建構函式中存取 this 之前,一定要呼叫 super(),它負責初始化 this
this.state = {age: 18}
}
render() {
const c = React.createElement
return React.createElement(
'form',
{ className: 'sub-class' },
c('p', { },
c('input', {type: 'text', value: this.state.age})
),
c('p', { },
c('input', {type: 'submit', value: 'submit'})
),
)
}
}
</script>
生成的表單也很簡單,狀態資料 age 也已經在 input 元素中成功顯示:
<div id="root">
<div class="parent-class">
<form class="sub-class">
<p><input type="text" value="18"></p>
<p><input type="submit" value="submit"></p>
</form>
</div>
</div>
現在需要專門的方法更新 state 中的資料。不能直接修改(例如 this.state.age = 19
),因為 React 需要跟蹤狀態,並保證虛擬 dom 和真實 dom 的同步。得通過 React 提供的特殊通道(this.setState()
) 來更新 React 類元件中的狀態。
setState 不會立即更新元件,React 會根據狀態變化批次更新以便使效率最大化,也就是說 React 會以它最高效的方法基於新狀態更新 dom,做到儘可能快。
Tip: 不要直接修改 state 的範例請看 這裡
以前我們直接操作 dom,於是可以通過 addEventListener
註冊事件;現在不直接操作 dom,而是和 React 元素打交道,那麼 React 應該提供對應的事件機制,最好和我們之前的習慣相同,而 React 確實是這樣做的。
React 實現了一個合成事件系統作為虛擬 Dom 的一部分,它會將瀏覽器中的事件轉為 React 應用的事件。可以設定響應瀏覽器事件的事件處理器,就像通常用 js 那樣做就好。區別是 React 的事件是設定在 React 元素或元件自身上,而不是用 addEventListener。
React 能監聽瀏覽器中很多不同事件,涵蓋了幾乎所有的互動(點選、提交、捲動等)
接下來我們就可以用來自這些事件(比如文字變化時的事件 onchange
)的資料來更新元件狀態。
接著上面範例,需求是:更改 input[type=text]
的值,對應 state 中的 age 也會同步,點選 submit 能提交。
程式碼如下:
<script>
class MyComponent extends React.Component {
render() {
const c = React.createElement
return React.createElement(
'div',
{ className: 'parent-class' },
this.props.children
)
}
}
class MySubComponent extends React.Component {
constructor(props) {
// 如果不需要使用 this.props,則可以是 super()
super(props)
// 在建構函式中存取 this 之前,一定要呼叫 super(),它負責初始化 this
this.state = { age: 18 }
// 自定義的方法,react 沒有幫我們處理 this。所以這裡需要我們自己繫結一下
this.handleTextChange = this.handleTextChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleTextChange(evt) {
// 不手動繫結 this,則為 undefined
// console.log('this', this)
const v = evt.target.value
// 用來自事件的資料更新元件狀態。否則介面是看不到 age 的最新值的
this.setState({ age: v })
}
// React 要阻止預設行為,必須顯式的使用 preventDefault
handleSubmit(evt) {
evt.preventDefault()
// 提交表單。state {age: 18}
console.log('提交表單。state', this.state)
}
render() {
const c = React.createElement
return React.createElement(
'form',
{
className: 'sub-class',
onSubmit: this.handleSubmit
},
c('p', {},
c('input', {
type: 'text',
value: this.state.age,
// React 事件的命名採用小駝峰式(camelCase),而不是純小寫。例如在 html 中通常都是小寫(onclick)
onInput: this.handleTextChange
})
),
c('p', {},
c('input', { type: 'submit', value: 'submit' })
),
)
}
}
</script>
利用函數
可以將子元件的資料傳遞給父元件。核心程式碼如下:
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleSubmit(data) {
console.log('提交表單 data=', data)
}
render() {
const c = React.createElement
return React.createElement(
'div',
{ className: 'parent-class' },
React.createElement(MySubComponent, {
aClass: 'p-class',
cnt2: 'a am em element',
onFormSubmit: this.handleSubmit
})
)
}
}
class MySubComponent extends React.Component {
handleSubmit(evt) {
evt.preventDefault()
this.props.onFormSubmit(this.state)
}
}
在 React 中,資料自頂向下流動,可以通過 props 向子元件傳遞資訊並在子元件中使用這些資訊。表明可以將子元件的資料儲存在父元件中,並從那裡將資料傳遞給子元件。做個範例來驗證一下,定義三個元件(A、B、C),結構如下:
<div class='componentA'>
<p class='componentB'> apple </p>
<button class='componentC'>add apple</button>
</div>
資料存在 AComponent 中,每點選一次 CComponent 元件,就會要求 AComponent 增加一個 apple,渲染到頁面的 BComponent 元件也相應增加。
全部程式碼如下:
<script>
class AComponent extends React.Component {
constructor(props) {
super(props)
this.state = {apples: this.props.apples}
this.handleAddApple = this.handleAddApple.bind(this)
}
handleAddApple(data) {
this.setState({apples: [data, ...this.state.apples]})
}
render() {
const c = React.createElement
return c(
'div',
{ className: 'componentA' },
this.state.apples.map((item, index) => c(BComponent, {
content: item,
// 需要增加 key 屬性,否則報錯:
// Warning: Each child in a list should have a unique "key" prop.
key: index
})),
c(CComponent, {
onHandleAddApple: this.handleAddApple
})
)
}
}
class BComponent extends React.Component {
render() {
const c = React.createElement
return React.createElement(
'p',
{
className: 'componentB',
// key: this.props.key
},
this.props.content
)
}
}
class CComponent extends React.Component {
constructor(props) {
super(props)
this.handleAdd = this.handleAdd.bind(this)
}
// React 要阻止預設行為,必須顯式的使用 preventDefault
handleAdd(evt) {
this.props.onHandleAddApple('apple')
}
render() {
const c = React.createElement
return React.createElement(
'button',
{
className: 'componentC',
onClick: this.handleAdd
},
'add apple'
)
}
}
</script>
<script>
const App = React.createElement(AComponent, {
apples: ['apple']
},
)
ReactDOM.render(
App,
document.getElementById('root')
);
</script>
JSX 僅僅只是 React.createElement(component, props, ...children)
函數的語法糖 —— react 官網-深入 JSX
我們建議在 React 中配合使用 JSX,JSX 可以很好地描述 UI 應該呈現出它應有互動的本質形式 —— react 官網-JSX 簡介
jsx 讓人編寫類似於(但不是) HTML 的程式碼。
將上面增加 apple 的例子改為 jsx。全部程式碼如下:
<body>
<div id="root"></div>
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/[email protected]/prop-types.js"></script>
<!-- Babel 能夠轉換 JSX 語法 -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
class AComponent extends React.Component {
constructor(props) {
super(props)
this.state = { apples: this.props.apples }
this.handleAddApple = this.handleAddApple.bind(this)
}
handleAddApple(data) {
this.setState({ apples: [data, ...this.state.apples] })
}
render() {
return <div className='componentA'>
{
this.state.apples.map(
(item, index) =>
(<BComponent content={item} key={index} />)
)
}
<CComponent onHandleAddApple={this.handleAddApple} />
</div>
}
}
class BComponent extends React.Component {
render() {
return <p className='componentB'>{this.props.content}</p>
}
}
class CComponent extends React.Component {
constructor(props) {
super(props)
this.handleAdd = this.handleAdd.bind(this)
}
handleAdd(evt) {
this.props.onHandleAddApple('apple')
}
render() {
return <button className="componentC" onClick={this.handleAdd}>add apple</button>
}
}
</script>
<script type="text/babel">
const App = <AComponent apples={['apple']} />
ReactDOM.render(
App,
document.getElementById('root')
);
</script>
</body>
jsx 除了類似於 HTML 且語法簡單,另一個好處是宣告式
和封裝
。通過將組成檢視的程式碼和相關聯的方法包含在一起,使用者建立了一個功能組。本質上,需要知道的有關元件的所有資訊都匯聚在此,無關緊要的東西都被隱藏起來,意味著使用者更容易的思考元件,並且更加清楚他們作為一個系統是如何工作的。
主要注意,JSX 不是 html,只會轉譯成常規 React 程式碼。它的語法和慣例也不完全相同,需要關注一些細微的差異(偶爾有些「破費思量之處」),比如:
<AComponent apples={['apple']} />
Tip:比如class 得換成 className,更多 jsx 語法規則請看 這裡
其他章節請看: