jsx介紹
jsx是一種JavaScript的語法擴(kuò)展(eXtension),也在很多地方稱之為JavaScript XML,因?yàn)榭雌鹁褪且欢蝀ML語法,用于描述UI界面,并且可以和JavaScript代碼結(jié)合使用。
比起vue中的模板語法,更加靈活,且不需要學(xué)習(xí)模板語法中的特定標(biāo)簽,比如:v-if
、v-for
、v-bind
等,而是直接使用JavaScript語法就可以實(shí)現(xiàn)這些標(biāo)簽的功能。
為何React中編寫UI界面需要使用jsx語法呢?
因?yàn)樵鷋tml和js兩者是密不可分的兩個部分,比如操作html元素時:
- 使用js選中元素,然后修改元素;
- 元素上綁定有事件時,需要綁定對應(yīng)的事件函數(shù);
- js中某些數(shù)據(jù)發(fā)生變化時,需要修改html元素。
索性,React直接將兩者組合在一起進(jìn)行管理。
jsx語法
書寫規(guī)范
- 頂層只允許有一個根元素,和vue2類似;
- 為了方便閱讀,通常在外層包裹一個
()
; - 可以使用單標(biāo)簽和雙標(biāo)簽,但是單標(biāo)簽一定要包含結(jié)束符號,如:
<button/>
。
// 定義App根組件
class App extends React.Component {
render() {
{/* 2.return外層,最好包裹一個() */}
return (
{/* 1.頂層只允許有一個根元素 */}
<div>
{/* 3.支持單標(biāo)簽和雙標(biāo)簽 */}
<h2>h2</h2>
<br/>
</div>
</div>
)
}
}
基本使用
1.添加注釋
在jsx中,添加注釋使用這樣的格式:
{/* 注釋內(nèi)容 */}
2.使用變量
- 當(dāng)變量是Number、String、Array類型時,可以直接顯示
- 當(dāng)變量是null、undefined、Boolean類型時,內(nèi)容顯示為空,如果需要顯示,需要轉(zhuǎn)換為字符串;
- Object對象類型不能作為子元素(not valid as a React child)
class App extends React.Component {
constructor() {
super()
this.state = {
// Number/String/Array類型
name: 'easylee',
age: 18,
movies: ['xxx', 'xxx'],
// null/undefined/boolean類型
varNull: null,
varUndefined: undefined,
varBoolean: true,
// Object對象
friends: { name: 'foo' },
}
}
render() {
const { name, age, movies } = this.state
const { varNull, varUndefined, varBoolean } = this.state
const { friends } = this.state
return (
<div>
{/* 正常顯示 */}
<h2>name: {name}</h2>
<h2>age: {age}</h2>
<h2>movies: {movies}</h2>
{/* 顯示為空 */}
<h2>null: {varNull}</h2>
<h2>undefined: {varUndefined}</h2>
<h2>Boolean: {varBoolean}</h2>
{/* 顯示為字符串 */}
<h2>null: {varNull + ''}</h2>
<h2>undefined: {String(varUndefined)}</h2>
<h2>Boolean: {varBoolean.toString()}</h2>
{/* 對象不允許直接作為子元素,必須具體到對象的屬性 */}
{/* <h2>friends: {friends}</h2> */}
<h2>friends: {friends.name}</h2>
</div>
)
}
}
const root = ReactDOM.createRoot(document.querySelector('#root'))
root.render(<App />)
3.使用表達(dá)式
和vue中使用模板語法一樣,只有可以放在 return
后的語句,都是表達(dá)式,可以直接在jsx中使用。
主要包含:
- 運(yùn)算表達(dá)式;
- 三元表達(dá)式;
- 可執(zhí)行函數(shù)。
class App extends React.Component {
constructor() {
super()
this.state = {
firstName: 'easy',
lastName: 'lee',
age: 18,
movies: ['foo', 'bar'],
}
}
getMovies() {
return this.state.movies
}
render() {
const { firstName, lastName, age } = this.state
return (
<div>
{/* 表達(dá)式 */}
<h2>{1 + 1}</h2>
<h2>{firstName + ' ' + lastName}</h2>
<h2>{age >= 18 ? '成年' : '未成年'}</h2>
<h2>{this.getMovies()}</h2>
</div>
)
}
}
4.綁定屬性
給html元素或者組件添加屬性,和直接使用變量類似,都使用{}
包裹即可,綁定 class
和 style
有一點(diǎn)不同:
- 基本屬性,直接綁定即可;
- class屬性,需要使用
className
代替class
,因?yàn)閏lass在js中也表示類; - style屬性,需要傳遞一個對象。
class App extends React.Component {
constructor() {
super()
this.state = {
title: 'title',
imgUrl: 'http://xxx.xxx.xxx',
isActive: true,
objStyle: { color: 'red', fontSize: '20px' },
}
}
render() {
const { title, imgUrl, isActive, objStyle } = this.state
const className = `foo ${isActive ? 'active' : ''}`
return (
<div>
{/* 基本屬性綁定 */}
<h2 title={title}>h2</h2>
<img src={imgUrl} />
{/* 綁定class屬性 */}
<h2 className='className'>h2</h2>
{/* 綁定style屬性,objStyle必須是一個對象 */}
<h2 style={objStyle}>h2</h2>
</div>
)
}
}
5.綁定事件
React中綁定事件需要使用小駝峰格式。
class App extends React.Component {
constructor() {
super()
this.state = {
name: 'easylee',
}
}
btnClick() {
console.log('btnClick')
}
btnClick2() {
this.setState({
name: 'easy',
})
}
btnClick3(event, name, age) {
console.log(event, name, age)
}
render() {
return (
<div>
{/* 事件綁定基本使用 */}
<button onClick={this.btnClick}>按鈕</button>
<button onClick={() => this.btnClick2()}>按鈕</button>
<h2>{this.state.name}</h2>
{/* 傳遞參數(shù) */}
<button onClick={event => this.btnClick3(event, 'easylee', 18)}>按鈕</button>
</div>
)
}
}
上例代碼中,當(dāng)我們綁定的函數(shù)體內(nèi)部使用了this
,傳遞給onClick的函數(shù)需要綁定指定的this,通常有下面幾種方式進(jìn)行綁定,原因和解決方法具體可以看:https://www.cnblogs.com/easy1996/p/17952054。
同時,給綁定函數(shù)傳遞參數(shù)時,onClick會默認(rèn)給綁定的函數(shù)第一個參數(shù)傳遞 event
參數(shù)。
6.條件渲染
jsx中條件渲染可以使用多種方式:
- 直接使用JavaScript if進(jìn)行條件判斷;
- 使用三元運(yùn)算符;
- 使用邏輯運(yùn)算符。
class App extends React.Component {
constructor() {
super()
this.state = {
isOk: true,
friend: { name: 'foo' },
}
}
render() {
const { isOk, friend } = this.state
let showContent = null
if (isOk) {
showContent = <h2>正常</h2>
} else {
showContent = <h2>異常</h2>
}
return (
<div>
{/* 1.使用if進(jìn)行判斷,注意渲染函數(shù)中不能使用if判斷,應(yīng)該寫在render()外 */}
<h2>{showContent}</h2>
{/* 2.三元運(yùn)算符 */}
<h2>{isOk ? <span>正常</span> : <span>異常</span>}</h2>
{/* 3.&&邏輯與判斷,為空或者undefined時,就會默認(rèn)不顯示 */}
<h2>{friend && <span>{friend.name}</span>}</h2>
</div>
)
}
}
7.列表渲染
列表渲染通常使用高階函數(shù),比如 map
、filter
等,通過前面的介紹,我們知道表達(dá)式可以直接在 {}
中使用,直接使用這些高階函數(shù)即可渲染列表。
class App extends React.Component {
constructor() {
super()
this.state = {
list: [
{
name: 'easylee',
age: 18,
},
{
name: 'foo',
age: 20,
},
],
}
}
render() {
const { list } = this.state
return (
<ul>
{list.map(item => {
return (
<li key={item.name}>
<h2>name: {item.name}</h2>
<h2>age: {item.age}</h2>
</li>
)
})}
</ul>
)
}
}
上面代碼中,{}
內(nèi)通過高階函數(shù),獲取到一個 li
元素數(shù)組,然后直接渲染這個數(shù)組,即完成了列表的渲染。
當(dāng)然也可以把高階函數(shù)這塊代碼提取到其它地方或者創(chuàng)建一個函數(shù)專門生成 li
元素數(shù)組。
同時需要注意,和vue一樣,列表元素都需要設(shè)置一個 key
,以提高diff算法時的效率。
jsx轉(zhuǎn)換原理
jsx通過babel進(jìn)行轉(zhuǎn)換,僅僅是一個語法糖,本質(zhì)上,所有的jsx代碼最終都將轉(zhuǎn)換為 React.createElement(type, config, children)
函數(shù),這個函數(shù)包含三個參數(shù):
- type:當(dāng)前元素的類型,比如div就傳div,組件就傳組件名;
- config:當(dāng)前元素的各種屬性,比如class屬性,src屬性等;
- children:當(dāng)前元素的下級元素,比如ul下的li,里面又是一個
React.createElement(type, config, children)
函數(shù),是嵌套的結(jié)構(gòu)。
以這段代碼為例:
class App extends React.Component {
// ...
render() {
return (
<div>
<div className='header'>Header</div>
<ul className='Content'>
<li>列表數(shù)據(jù)1</li>
<li>列表數(shù)據(jù)2</li>
</ul>
</div>
)
}
}
render函數(shù)渲染中return的部分,最終會轉(zhuǎn)換為React.createElement
函數(shù),直接放到return中,渲染結(jié)果一樣:
render() {
return React.createElement(
'div',
null,
React.createElement(
'div',
{
className: 'header',
},
'Header',
),
React.createElement(
'ul',
{
className: 'Content',
},
React.createElement('li', null, '\u5217\u8868\u6570\u636E1'),
React.createElement('li', null, '\u5217\u8868\u6570\u636E2'),
),
)
}
這個代碼,可以通過babel在線轉(zhuǎn)換查看:Babel · The compiler for next generation JavaScript
可以直接編寫 React.createElement
來生成UI界面,從而不使用babel轉(zhuǎn)換。
通過上面的 React.createElement
函數(shù),可以創(chuàng)建出一個 ReactElement
對象,React利用ReactElement對象組成JavaScript的對象樹,這個對象樹就是虛擬DOM。文章來源:http://www.zghlxwxcb.cn/news/detail-776990.html
編寫jsx代碼,然后調(diào)用createElement函數(shù)創(chuàng)建ReactElement對象,react再經(jīng)過一些處理,最終使用JavaScript的createElement方法,再轉(zhuǎn)換為真實(shí)DOM。文章來源地址http://www.zghlxwxcb.cn/news/detail-776990.html
到了這里,關(guān)于React jsx 語法解析 & 轉(zhuǎn)換原理的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!