摘要:語(yǔ)法是一種語(yǔ)法的拓展語(yǔ)言,在中官方也推薦使用描述用戶界面,使用起來會(huì)比較快捷而且易讀不是一門新的語(yǔ)言,可以理解為是一種語(yǔ)法糖,作用就是能夠讓我們更加直觀的在中創(chuàng)建標(biāo)簽,最終還是會(huì)被編譯為語(yǔ)法,例如我們看一段代碼上面的語(yǔ)法最終會(huì)被編譯為語(yǔ)法,
Reatc JSX語(yǔ)法
jsx是一種JavaScript語(yǔ)法的拓展語(yǔ)言,在React中官方也推薦使用jsx描述用戶界面,使用起來會(huì)比較快捷而且易讀
jsx不是一門新的語(yǔ)言,可以理解為是一種語(yǔ)法糖,作用就是能夠讓我們更加直觀的在js中創(chuàng)建html標(biāo)簽,jsx最終還是會(huì)被編譯為JavaScript語(yǔ)法,例如我們看一段jsx代碼:
/*jsx*/ ReactDOM.render(, document.querySelector("#root") )hello world
上面的jsx語(yǔ)法最終會(huì)被編譯為JavaScript語(yǔ)法,中間就是通過一個(gè)React.createElement的方法來轉(zhuǎn)化,轉(zhuǎn)換后就是下面這段代碼
ReactDOM.render( React.createElement( "div", {className:"wrap"}, "", React.createElement( "h1", null, "hello world" ) ), document.querySelector("#root") )
比較兩段代碼就可以看出來使用js語(yǔ)法來寫的話實(shí)在不夠簡(jiǎn)練,所以我們通常還是使用jsx的語(yǔ)法
在使用jsx的時(shí)候,需要注意幾個(gè)點(diǎn)
在使用jsx的地方,要注意我們的代碼不能被JavaScript引擎直接解析,所以要在為script標(biāo)簽設(shè)置特殊的type屬性, 阻止JavaScript引擎的解析
在jsx中只能有一個(gè)根節(jié)點(diǎn),如果存在多個(gè)根節(jié)點(diǎn)會(huì)報(bào)錯(cuò),jsx同時(shí)也可以進(jìn)行標(biāo)簽的嵌套
ReactDOM.render(/*根節(jié)點(diǎn)*/, document.querySelector("#root") )hello world
在jsx中,我們雖然寫的時(shí)候看起來比較像是直接寫html,但實(shí)際上還是JavaScript,所以需要使用JavaScript的語(yǔ)法,例如我們?cè)跒闃?biāo)簽添加class屬性時(shí),不能寫class,而是要使用JavaScript語(yǔ)法的className,這樣才能被正確的解析
ReactDOM.render(, document.querySelector("#root") )
同樣的其他一些屬性也需要轉(zhuǎn)化為駝峰寫法,如tabindex?則對(duì)應(yīng)著?tabIndex
在jsx中使用單標(biāo)簽,需要在結(jié)尾處使用/>,否則不能夠被正確的解析
ReactDOM.render(, document.querySelector("#root") )
在jsx中可以任意的使用JavaScript的表達(dá)式,但是需要將表達(dá)式放置在{}中
const obj = { name: "tom", age: (age) => { return age; } } ReactDOM.render(, document.querySelector("#root") ) /*編譯結(jié)果*/ //我是tom,年齡是18,2+2是8,0>1的結(jié)果是false我是{obj.name},年齡是{obj.age(18)},2+2是{3 + 5},0>1的結(jié)果是{0 > 1 ? "true" : "false"}
由于jsx本身就是JavaScript,所以我們也可以通過條件判斷來決定控制模板的內(nèi)容
const obj = { name: "tom", age: (age) => { return age; } }; function judgment(user) { let component; component = user ?控制樣式:我是{obj.name},年齡是{obj.age(18)},2+2是{3 + 5},0>1的結(jié)果是{0 > 1 ? "true" : "false"}
出現(xiàn)錯(cuò)誤了哦return component; } ReactDOM.render( judgment(true), document.querySelector("#root") )
React中并沒有提供其他框架中的例如ng-show、v-if等命令,這些都是需要我們自己手動(dòng)去寫的
控制元素的顯示/隱藏
class Control extends React.Component { constructor(...args) { super(...args); this.state = { flag: "block" } } fn() { this.setState({ flag: this.state.flag == "block" ? "none" : "block" }) } render() { return} } ReactDOM.render(, document.querySelector("#root") )
控制class樣式
class Control extends React.Component { constructor(...args) { super(...args); this.state = { flag: true } } fn() { this.setState({ flag:!this.state.flag }) } render() { return} } ReactDOM.render(是否渲染
, document.querySelector("#root") )
在實(shí)際開發(fā)中上面的方法都不是很直觀,推薦使用classnames庫(kù)
class Control extends React.Component { constructor(...args) { super(...args); this.state = { flag: false } } fn() { this.setState({ flag:!this.state.flag }) } render() { return組件} } ReactDOM.render(是否渲染
{ this.state.flag ? : null }, document.querySelector("#root") )
組件這個(gè)概念現(xiàn)在也是非常流行了,如果之前沒有使用過其他框架的話可以用一個(gè)相對(duì)比較通俗的例子來理解組件的概念,Moto之前推出過好幾款模塊化的手機(jī),該手機(jī)包括屏幕,處理器,內(nèi)存,電池,攝像頭等,都支持自由更換拼裝,然后組裝成一個(gè)完整的手機(jī)
, document.querySelector("#root") )
注意,使用組件時(shí),組件名稱一定要是大寫字母開頭的,否則的話會(huì)被認(rèn)為是普通的html文本進(jìn)行解析,同時(shí)也需要注意的是組件內(nèi)只允許有一個(gè)根元素
組件的嵌套在React中,組件之間是可以嵌套使用的
class Hello extends React.Component { render() { return容器類組件hello} } class Wrold extends React.Component { render() { return} } ReactDOM.render(world
, document.querySelector("#root") )
這個(gè)概念類似于Vue中的插槽,如果沒有Vue知識(shí)的可以將這個(gè)理解為在在使用某個(gè)組件時(shí)我們?cè)谠摻M件內(nèi)插入一些DOM元素,而且要保證這些DOM元素能夠被正確渲染
class FancyBorder extends React.Component { render() { return ({this.props.children}) } } ReactDOM.render(, document.querySelector("#root") ) Lorem ipsum dolor sit amet.
Lorem ipsum dolor.
這里就借用一下Vue的概念,我們將組件中設(shè)定了{this.props.children} 的部分稱為插槽
在需要插入來自調(diào)用者的DOM的部分寫入{props.children},之后調(diào)用者插入的代碼就會(huì)在我們寫入了{props.children}的位置上被展示
我們此時(shí)可以打印一下props.children,可以發(fā)現(xiàn)得到的是一個(gè)數(shù)組的結(jié)果
, document.querySelector("#root") ) 組件之間的通信
class Child extends React.Component { render() { returnhello {this.props.name}} } class Parent extends React.Component { render() { return} } ReactDOM.render(, document.querySelector("#root") )
props方法時(shí)官方提供的接口,我們?cè)谑褂媒M件時(shí),在引用子組件處,將要傳遞的內(nèi)容以設(shè)置屬性的方式添加到子組件,在子組件中通過this.props[父組件設(shè)置的屬性名]的格式就可以獲取到父組件傳遞的信息,通過props可以傳遞字符串、數(shù)字、對(duì)象、數(shù)組、函數(shù) ,子組件在可以通過this.props來查看當(dāng)前所有接收到的值
class Child extends React.Component { click(e) { console.log(this.props.data,"child"); e.stopPropagation(); } render() { returnhello {this.props.data.name}} } class Parent extends React.Component { constructor() { super(); this.state = { obj: { name: "tom", age: 18 } } } click() { console.log(this,"parent") } render() { return} } ReactDOM.render(, document.querySelector("#root") )
class Child extends React.Component { render() { return } } class Parent extends React.Component { click(e) { console.log(this) e.stopPropagation() } render() { return} } ReactDOM.render(, document.querySelector("#root") )
傳遞事件的時(shí)候可以通過bind改變我們最初事件的this的指向,這里我們看打印的結(jié)果,this的指向在child中指向的是child組件
狀態(tài)提升這個(gè)概念其實(shí)可以理解為我們?cè)谄渌蚣苤惺褂玫慕咏M件的信息傳遞給父組件的一個(gè)過程,但是在react中并沒有提供直接的方法,需要我們自己進(jìn)行處理,實(shí)現(xiàn)的代碼如下:
class Child extends React.Component { click(i,e) { i++; this.props.P_click(i); e.stopPropagation(); } render() { return} } class Parent extends React.Component { constructor() { super(); this.state = { index: 1 } this.P_Click = this.P_Click.bind(this) } change(data) { this.setState({ index: data }); } render() { return{this.state.index}} } ReactDOM.render(, document.querySelector("#root") )
我們首先來說一下大概的思路
在父組件中設(shè)置一個(gè)方法change,在該方法中設(shè)置改變我們指定的變量值的處理
change(data) { this.setState({ index: data }); }
將該方法傳遞給子組件,同時(shí)也將我們要要改變的父組件的值傳遞給子組件
在子組件操作時(shí),例如點(diǎn)擊時(shí),調(diào)用我們?cè)诟附M件中傳入的change方法,并改變由父組件發(fā)送過來的數(shù)據(jù)(index),回傳給change方法
click(i,e) { i++; this.props.P_click(i) e.stopPropagation(); }
change方法被調(diào)用,通過this.setState響應(yīng)的改變了父組件中index值
可以看出來確實(shí)很麻煩,由于沒有像vue那樣提供$emit方法,所以需要我們自己迂回寫一系列操作,包括如果我們想要在同級(jí)的組件之間傳遞數(shù)據(jù),我們需要 子組件數(shù)據(jù) => 父組件 => 子組件兄弟組件
推薦使用Redux來進(jìn)行組件之間的數(shù)據(jù)傳遞
響應(yīng)式的更新數(shù)據(jù) 生命周期, document.querySelector("#root") )
在執(zhí)行上訴代碼之后,我們會(huì)看到一行報(bào)錯(cuò)
react.js:369 Warning: Each child in an array or iterator should have a unique "key" prop.Check the render method of Lists.
這是React提示需要在為我們通過遍歷渲染的li添加key值,采用如下操作
React是不會(huì)去渲染之前已經(jīng)存在的元素,這也是React的高效性的原因之一,key值可以幫助React識(shí)別那些元素發(fā)生了變化,那些沒有變化,從而使React在渲染時(shí)保留那些之前已經(jīng)被渲染的元素
還是上面的代碼,我們打開控制臺(tái),在為第一個(gè)li添加一個(gè)臨時(shí)的color,然后點(diǎn)擊添加按鈕,可以發(fā)現(xiàn)這個(gè)li的樣式依然被保持了,說明React沒用重新渲染該元素
, document.querySelector("#root") )
然后我們嘗試在輸入框中輸入文字會(huì)發(fā)現(xiàn)不論輸入什么內(nèi)容,輸入框中會(huì)依然保持是react,這是因?yàn)樵谖覀儎?chuàng)建input的時(shí)候,value就已經(jīng)被react劫持了
react也會(huì)特別貼心的進(jìn)行提示
Failed prop type: You provided a value prop to a form field without an onChange handler. This will render a read-only field. If the field should be mutable use defaultValue. Otherwise, set either onChange or readOnly. in input
根據(jù)提示,我們可以發(fā)現(xiàn)我們需要設(shè)置為如下的格式
ReactDOM.render( , document.querySelector("#root") )
這個(gè)時(shí)候我們就可以正常的修改表單數(shù)據(jù)了,同樣的會(huì)被react劫持的還有一個(gè)屬性,就是checked,在使用時(shí)同樣需要轉(zhuǎn)換為React提供的defaultChecked
react中是沒有雙向綁定這個(gè)概念的,實(shí)際的react其實(shí)可以理解為是一個(gè)單向的數(shù)據(jù)綁定,所有的頂層具有的state做為數(shù)據(jù)流通過props向下傳遞給子組件,然后在數(shù)據(jù)改變的時(shí)候重新調(diào)用render,重而重新渲染頁(yè)面
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/97299.html
摘要:希望大家在這浮夸的前端圈里,保持冷靜,堅(jiān)持每天花分鐘來學(xué)習(xí)與思考。 今天的React題沒有太多的故事…… 半個(gè)月前出了248個(gè)Vue的知識(shí)點(diǎn),受到很多朋友的關(guān)注,都強(qiáng)烈要求再出多些React相前的面試題,受到大家的邀請(qǐng),我又找了20多個(gè)React的使用者,他們給出了328道React的面試題,由我整理好發(fā)給大家,同時(shí)發(fā)布在了前端面試每日3+1的React專題,希望對(duì)大家有所幫助,同時(shí)大...
摘要:中的元素組件實(shí)例和節(jié)點(diǎn),是中關(guān)系密切的個(gè)概念,也是很容易讓初學(xué)者迷惑的個(gè)概念。組件和元素關(guān)系密切,組件最核心的作用是返回元素。只有組件實(shí)例化后,每一個(gè)組件實(shí)例才有了自己的和,才持有對(duì)它的節(jié)點(diǎn)和子組件實(shí)例的引用。 React 深入系列,深入講解了React中的重點(diǎn)概念、特性和模式等,旨在幫助大家加深對(duì)React的理解,以及在項(xiàng)目中更加靈活地使用React。 React 中的元素、組件、實(shí)...
摘要:中的元素組件實(shí)例和節(jié)點(diǎn),是中關(guān)系密切的個(gè)概念,也是很容易讓初學(xué)者迷惑的個(gè)概念。組件和元素關(guān)系密切,組件最核心的作用是返回元素。只有組件實(shí)例化后,每一個(gè)組件實(shí)例才有了自己的和,才持有對(duì)它的節(jié)點(diǎn)和子組件實(shí)例的引用。 文:徐超,《React進(jìn)階之路》作者授權(quán)發(fā)布,轉(zhuǎn)載請(qǐng)注明作者及出處 React 深入系列,深入講解了React中的重點(diǎn)概念、特性和模式等,旨在幫助大家加深對(duì)React的理解...
摘要:在前端開發(fā)過程中,源碼解讀是必不可少的一個(gè)環(huán)節(jié),我們直接進(jìn)入主題,注意當(dāng)前版本號(hào)。注意包文件僅僅是的必要的功能性的定義,它必須要結(jié)合一起使用下是,原生環(huán)境下是。 在前端開發(fā)過程中,源碼解讀是必不可少的一個(gè)環(huán)節(jié),我們直接進(jìn)入主題,注意當(dāng)前 React 版本號(hào) 16.8.6。 注意:react 包文件僅僅是 React components 的必要的、功能性的定義,它必須要結(jié)合 React...
摘要:內(nèi)部機(jī)制探秘和文末附彩蛋和源碼這篇文章比較偏基礎(chǔ),但是對(duì)入門內(nèi)部機(jī)制和實(shí)現(xiàn)原理卻至關(guān)重要。當(dāng)然也需要明白一些淺顯的內(nèi)部工作機(jī)制。當(dāng)改變出現(xiàn)時(shí),相比于真實(shí)更新虛擬的性能優(yōu)勢(shì)非常明顯。直到最終,會(huì)得到完整的表述樹的對(duì)象。 React 內(nèi)部機(jī)制探秘 - React Component 和 Element(文末附彩蛋demo和源碼) 這篇文章比較偏基礎(chǔ),但是對(duì)入門 React 內(nèi)部機(jī)制和實(shí)現(xiàn)原...
摘要:本文翻譯自原作者如果有任何版權(quán)問題,請(qǐng)聯(lián)系當(dāng)你在組件中調(diào)用時(shí),你覺得會(huì)發(fā)生什么當(dāng)然,會(huì)用這條狀態(tài)重新渲染組件并且更新匹配到的,然后返回元素。如果你之前使用過一些渲染器比如說,你可能知道在頁(yè)面中使用超過一個(gè)渲染器是沒什么問題的。 本文翻譯自:How Does setState Know What to Do?原作者:Dan Abramov 如果有任何版權(quán)問題,請(qǐng)聯(lián)系shuirong199...
閱讀 2999·2021-10-27 14:16
閱讀 705·2021-10-13 09:39
閱讀 3715·2021-09-29 09:46
閱讀 2100·2019-08-30 15:54
閱讀 2607·2019-08-30 15:52
閱讀 3004·2019-08-30 15:44
閱讀 1115·2019-08-30 15:44
閱讀 507·2019-08-30 10:51