目錄:
什麼是JSX
// 這就是jsx表達式
const h1 = (<h1>hello user, i am jsx expresion</h1>);
// 這是複雜一點的jsx表達式
const complexExpresion = (
<div>
<header>我是頭部</header>
<div className='content'>
<p>helloWorld</p>
</div>
<footer>我是底部</footer>
</div>
)
JSX是JS的一種語法擴展,他允許我們在js文件中寫html結構並且能夠跟js進行直接交互 在語法上有點類似於Vue的模板語法, 但是又不盡相同, 去除了過多的語言魔法(比如Vue中的v-on
, v-if
等, 但是在JSX中可以直接使用js攜帶的所有功能, 所以會顯得特別的靈活和強大)
JSX表達式的特點
- JSX表達式最終會被babel編譯成React.createElement
const span = (<span>helloWorld</span>);
// 上面的代碼等同於
const span = React.createElement('span', {},'helloWorld');
- JSX表達式必須被閉合(遵守xml規範)
// 下面這種寫法我們可以看到img標籤沒有被閉合, 這在最新的html5規範中是支持的, 但是在react中這樣會報錯
const errorImg = (<img src='https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3396435274,4251997814&fm=26&gp=0.jpg'>);
// 可以寫成如下寫法
// 1. 單標籤閉合
const niceImg = (<img src='https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3396435274,4251997814&fm=26&gp=0.jpg' />);
// 2. 雙標籤閉合
const niceImg = (<img src='https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3396435274,4251997814&fm=26&gp=0.jpg'></img>);
- JSX表達式有且只有一個根節點
// 由於JSX表達式最終會被babel編譯成React.createElement
const span = (<span></span>);
// 上方表達式最終會被babel編譯成如下格式
const span = React.createElement('span', {},, null);
// 那麼就註定了JSX表達式不能具有多個根元素, 因爲假設我們寫成如下這樣
const span = (<span></span><a></a>);
// 你讓babel咋編譯, React.createElement第一個參數就只能有一個, 你這擱倆
如果有特殊情況, 某些場景中必須存在兩個根節點, 則要使用React.Fragment
const demo = (
<React.Fragment>
<span></span>
<a></a>
</React.Fragment>
)
// 至於React.Fragment的原理在你學到React高階組件的時候希望你留意一下組件中的children屬性
// 同時React.Fragment還有一個語法糖如下
const demo2 = (
{/*兩個空標籤進行包裹*/}
<>
<span></span>
<a></a>
</>
)
- JSX表達式中的註釋必須寫成如下形式
const div = (
<div>
{/*這是註釋*/}
</div>
)
- 在JSX表達式中寫屬性必須使用小駝峯式命名, 且有些時候屬性和關鍵字重名的話必須改名(比如class)
const h1 = (
<h1 className='demo' style={{
backgroundColor: 'red'
width: '100px';
}}>helloWorld</h1>
)
// 注意上方的style, style對應的是js中的style對象
// 我們需要寫兩個大括號, 最外層的大括號代表的是JSX表達式的標識符括號, 而裏層的對象表示就是一個style對象, 兩個括號的含義不一樣
- 在JSX中插入表達式
// 在Vue中我們知道插入表達式 要使用插值表達式也就是 {{ }} 這哥們, 而在React中我們使用{}單括號
const a = 10;
const b = 20;
const h1 = (
<h1>{ a } + { b } = { a + b }</h1>
)
// 這一對大括號中跟Vue能夠放置的東西差不多
// 1. 函數執行
function foo() {
return 'helloWorld';
}
const h1 = (
<h1>{ foo() }</h1>
)
// 2. 數組(以及所有可迭代數據結構)
const arr = [1, 2, 3]
const h1 = (
<h1>{ arr }</h1>
)
// 3. null, undefined, false, '' 在頁面中在頁面中都呈現爲空, 但是元素結構會在
const demo = null;
const h1 = (
<h1>{ demo }</h1>
)
// 4. &&, ||, 三元運算符
const h1 = (
<h1>
{ 1 > 0 ? '你好' : '不太好' }
</h1>
)
// 5. React元素對象
const li = (<li>helloWorld</li>);
const h1 = (
<ul>
{ li }
</ul>
)
// 同時我們也可以渲染複雜數據
const arr = [{name: 'loki'}, {name: 'thor'}];
const reactElementList = arr.map(ele => <li key={ ele.name }>{ ele.name }</li>);
const ul = (
<ul>
{ reactElementList }
</ul>
)
// 渲染結果不用多說也知道肯定兩個li標籤
// 而上面的key值跟Vue中v-for需要提供的key值作用一樣, 當我寫道react渲染原理的時候會詳細說
// 6. 屬性中放置JSX表達式
const imgUrl = 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3396435274,4251997814&fm=26&gp=0.jpg';
const img = (
<img src={ imgUrl } />
)
// 其他的暫時想不起來了, 隨用隨寫, JSX表達式過於靈活, 以至於騷操作特別多
關於上面的JSX中放置數組可以放置對象卻不可以的問題
跟Vue一樣, 從底層來說, 判斷一個複合數據能不能在頁面中被直接渲染出來的標準是他是否可迭代, 當我們在JSX中直接放置數組或者對象的時候, React會使用for..of
來進行迭代, 並將結果展示出來, 而對象不能被for...of
操作, 所以對象會報錯, 而數組可以被迭代, 同時Map, Set都可以被迭代, 所以Map, Set都可以被展示出來, 而關於React元素, 則是因爲React在底層做了一些特殊處理導致React元素對象也可以被渲染出來
const map = new Map([['name', 'loki']])
const h1 = (
<h1>
{ map }
</h1>
)
// 所以很多人片面的說在Vue或者React中使用的複合數據結構只有數組的話你就直接扇他
// 只要是具備迭代接口的數據都是可以進行渲染的, 數字字符串亦然, 這個不是什麼需要背的東西
// 懂原因就不用記那麼多的可被渲染數據結構了, 只需要記住一條: 可迭代可渲染
不過關於map這裏也只做個演示, 在實際工作中不要使用Map或者對象直接渲染進頁面, 因爲React在虛擬dom中可能會對對象或者Map監控失敗導致程序出現意外
- JSX對於XSS注入攻擊的預防
// 1. 自動編碼, 除了我們開發者自己編寫的代碼, 其他通過用戶輸入得到的數據JSX將會以字符串進行渲染
// 加入下面的context是用戶輸入的被我們截取到的文本
const context = '<div>helloWorld</div>'
const div = (
<div>
{/*context不會被渲染成div, 而是字符串<div>helloWorld</div>*/}
{ context }
</div>
)
// 2. dangerouslySetInnerHTML, 如果我們執意要將這些React認爲不安全的東西當成頁面結構來解析
// 那麼我們必須使用上面這個屬性
const context = '<div>helloWorld</div>'
const div = (
{/*經過如下的操作, context將會使用innerHTML來編譯context*/}
<div dangerouslySetInnerHTML = {{
__html: context
}}>
</div>
)
JSX元素的不可變性]
每一個我們書寫的JSX元素是一個對象, 但是這個對象中的所有屬性無法更改, 如果需要更改, 則必須重新創建新的JSX元素出來
這個你瞭解一下即可, 因爲這一時半會也說不清, 隨着慢慢的深入你就明白了, 你現在就記着, 你必須重新渲染頁面才能夠使得JSX元素中的內容進行更改
let context = 'helloWorld';
const h1 = (
<h1>{ context }</h1>
)
ReactDOM.render(h1, document.querySelector('#app'));
context = 'u r nice';
// 在上方更改了context以後必須重新調用render方法來完成頁面更新
ReactDOM.render(h1, document.querySelector('#app'));
// 我知道你會問性能問題, 放心, 虛擬dom讓你無懼性能挑戰兄弟, 原理部分見, 入門還是別想這麼多