React.js入門學(xué)習(xí)第一篇
一、JSX介紹
①定義
JSX=JavaScript XML,是一種在React組件內(nèi)部構(gòu)建標簽的類XML語法。React在不使用JSX的情況下一樣可以工作,但是使用JSX可以提高組件的可讀性,增強JS語義,結(jié)構(gòu)清晰,抽象程度高,代碼模塊化。因此推薦在React中使用JSX。
②特點
1、元素名首字母大寫
2、符合嵌套規(guī)則
3、可以寫入求值表達式
4、駝峰式命名
5、不能使用javascript原生函數(shù)的一些關(guān)鍵詞,如for和class。需要替換成htmlFor和className
③使用方法
1、使用動態(tài)值:JSX將兩個花括號之間的內(nèi)容{...}渲染為動態(tài)值,花括號指明了一個javascript上下文環(huán)境,花括號里面可以是一個變量,也可以是函數(shù)。 例如:
var name=“winty”; <p>{name}</p> function date(d){ return [ d.getFullYear(), d.getMonth()+1, d.getDate() ].join('-); }; <p>{date(new Date()}</p>
2.注釋:首先,在子節(jié)點中注釋要用大括號包裹起來,然后就可以單行注釋/**/,也可以多行注釋//。
var Hello=React.createClass({ render:function(){ return <p name="winty"> //set name Hello ,World /* 多行注釋 多行注釋 */ </p> } });
3.使用CSS內(nèi)聯(lián)樣式
var style={ color:#000; }; React.render(<div style={style}>....</div>,document.body);
4.使用條件判斷
//方法1,三目運算符 var Hello=React.createClass({ render:function(){ return <p>Hello,{this.props.name?this.props.name : "LuckyWinty"}</p> } }); //方法2,if-else語句 var Hello1=React.createClass({ getName:function(){ if(this.props.name) return this.props.name; else return "LuckyWinty"; render:function(){ return <p>Hello,{this.getName}</p> } }); //方法3,使用邏輯||運算符 var Hello3=React.createClass({ render:function(){ return <p>Hello,{this.props.name||"LuckyWinty"}</p> } });
④非DOM屬性介紹
JSX中有3個非DOM屬性,分別是:dangerouslySetInnerHTML、ref、key。
dangerouslySetInnerHTML:在JSX中直接插入HTML代碼,但是如果能避免使用這個屬性則盡量避免使用。
不合時宜的使用 innerHTML 可能會導(dǎo)致 cross-site scripting (XSS) 攻擊。 凈化用戶的輸入來顯示的時候,經(jīng)常會出現(xiàn)錯誤,不合適的凈化也是導(dǎo)致網(wǎng)頁攻擊 的原因之一。
在徹底的理解安全問題后果并正確地凈化數(shù)據(jù)之后,生成只包含唯一 key __html 的對象,并且對象的值是凈化后的數(shù)據(jù)。例如:
function createMarkup() { return {__html: 'First · Second'}; }; <div dangerouslySetInnerHTML={createMarkup()} />
ref:父組件引用子組件,你可以通過在屬性中設(shè)置期望的引用名來定義一個引用。例如:
... render:function(){ return <div> <input ref="MyInput" .../> </div> } ... //然后你就可以在組件中的任何地方使用this.refs.myInput獲取這個引用了
key:是一個可選的唯一標識符,通過給組件設(shè)置一個獨一無二的鍵,并確保它在一個渲染周期中保持一致,使得React能夠更只能地決定應(yīng)該重用一個組件還是銷毀并重建一個組件,進而提高渲染性能。例如:
var Hello3=React.createClass({ render:function(){ return <ul> <li key="1">1</li> <li key="2">2</li> <li key="3">3</li> </ul> } });
二、React組件生命周期詳解
組件本質(zhì)上就是狀態(tài)機,輸入確定,輸出一定確定。狀態(tài)和結(jié)果一一對應(yīng),從而使程序變得直觀。狀態(tài)發(fā)生轉(zhuǎn)換時會觸發(fā)不同的鉤子函數(shù),從而讓開發(fā)者有機會做出響應(yīng)??梢杂檬录乃悸穪砝斫鉅顟B(tài),但是事件與事件之間互相獨立,但是不同狀態(tài)之間可能會互相影響。
組件的所有狀態(tài)結(jié)合起來就成了組件的生命周期。即:初始化階段->運行中階段->銷毀階段。
不同生命周期內(nèi)可以自定義的函數(shù)
初始化階段:
①getDefaultProps:獲取默認屬性,只調(diào)用一次,是在createClass之后調(diào)用的。實例之間共享引用
②getInitialState:初始化每個實例的特有初始化狀態(tài)
③componentWillMount:mout就是裝載的意思,這個方法的意思就是說組件即將被裝載到頁面中,也是render之前最后一次修改狀態(tài)的機會
④render:組件在render函數(shù)生成虛擬節(jié)點,最后由react將虛擬節(jié)點變成真正的節(jié)點渲染到頁面上。只能訪問this.props和this.state,只有一個頂層組件,最好不要修改狀態(tài)和DOM輸出。
⑤componentDidMount:組件被裝載后才會被調(diào)用,也就是說調(diào)用這個方法的時候,組件已經(jīng)被渲染到了頁面上,這個時候可以修改DOM
這五個函數(shù)的執(zhí)行順序就是從上到下的。需要注意的是getDefaultProps只會在組件的第一個實例被初始化的時候被調(diào)用,也就是說第二個實例之后都是從getInitialState開始調(diào)用。同一個組件的所有實例的默認屬性都是一樣的。
主要測試代碼:
<script type="text/babel"> var Hello=React.createClass({ getDefaultProps:function(){ console.log("getDefaultProps, 1"); }, getInitialState:function(){ console.log("getInitialState, 2"); return null; }, componentWillMount:function(){ console.log("componentWillMount, 3"); }, render:function(){ console.log("render, 4"); return <p>Hi,LuckyWinty!</p> }, componentDidMount:function(){ console.log("componentDidMount, 5"); }, }); React.render(<Hello></Hello>,document.body); </script>
運行結(jié)果:
運行中階段:
①componentWillReceiveProps:這個函數(shù)在組件即將接收到屬性時觸發(fā)的,或者是父組件的屬性發(fā)生變化時,屬性在傳送到組件之前,開發(fā)者有機會通過這個函數(shù)去處理屬性。比如修改,更新內(nèi)部狀態(tài)等。
②shouldComponentUpdate:當(dāng)組件接收到新屬性或者新狀態(tài)的時候觸發(fā)的。這個是一個疑問函數(shù),也就是說我們可以告訴react不去更新某個組件。因為有時候?qū)傩曰蛘郀顟B(tài)并不會導(dǎo)致組件發(fā)生更新。在組件不需要更新的情況下,手動使shouldComponentUpdate返回false,這樣react就不需要再經(jīng)過render和diff算法去判斷是否要更新,從而提高性能。
③componentWillUpdate:render觸發(fā)之前觸發(fā),更新組件,不能修改屬性和狀態(tài)
④render:組件在render函數(shù)生成虛擬節(jié)點,最后由react將虛擬節(jié)點變成真正的節(jié)點渲染到頁面上,只能訪問this.props和this.state,只有一個頂層組件,最好不要修改狀態(tài)和DOM輸出。
⑤componentDidUpdate:render之后,真正的DOM被渲染之后調(diào)用
備注:這五個函數(shù)的執(zhí)行順序也是從上到下的。這個的測試代碼已上傳至:https://github.com/LuckyWinty/ReactStudyDemo,歡迎參考!
銷毀階段:
①componentWillUnmount:這個函數(shù)在銷毀操作真正執(zhí)行之前調(diào)用,給開發(fā)者最后的機會進行一些清理工作。
三、屬性、狀態(tài)的含義和用法
屬性的含義:
props=properties,屬性是不可以由組件自己進行修改的,組件的屬性是由父組件傳遞進來的。
屬性的用法:
一)、鍵值對
<Hello name="winty"/> 字符串 <Hello name={123}/> 大括號包裹的求值表達式 <Hello name={[1,2,3]}/> 傳入數(shù)組 <Hello name={winty}/> 變量
二)、展開定義(個人認為就是對象式定義)
var props={ one:"123", two:"22" }
這樣定義的話,理論上使用應(yīng)該是one={props.one}這樣調(diào)用,但是這樣寫起來比較繁瑣,而且如果數(shù)據(jù)被修改,就需要對應(yīng)修改相應(yīng)的賦值,并且無法動態(tài)地設(shè)置屬性,所以react中添加了一種展開語法:
<Hello {...props}/> //也就是三個點加上對象名稱。
這樣使用展開語法,react就會自動把對象中的變量和值當(dāng)作是屬性的賦值,所以Hello實際上就拿到了one、two兩個屬性,如果沒有三個點的話,Hello拿到的實際上就是props對象,使用的時候還需要自己從中取出變量和值
三)、調(diào)用react提供的setProps()函數(shù)(幾乎不用)
var instance=React.render(<HelloWorld></HelloWorld>,document.body); instance.setProps({name:"winty"});
狀態(tài)的含義:
state,狀態(tài)是由事物自行處理、不斷變化的
狀態(tài)的用法:
getInitialState:初始化實例的狀態(tài)
setState:更新組件狀態(tài),一旦更新了狀態(tài),那么就會觸發(fā)diff算法,檢查內(nèi)容是否發(fā)生變化,若有變化則更新組件,否則就不用。
屬性和狀態(tài)對比
相似點:都是純JS對象、都會觸發(fā)render更新、都具有確定性。
屬性和狀態(tài)區(qū)分:組件在運行時需要修改的數(shù)據(jù)就是狀態(tài)
四、React中事件的用法
事件處理函數(shù):React綁定事件處理器的方法和HTML語法非常類似,所有的事件在命名上與原生的javascript規(guī)范一致,并且會在相同的情境下觸發(fā)。
編寫函數(shù)
handleClick:function(){
...
}
綁定
onClick={this.handleClick}
各類事件詳細說明:
①移動設(shè)備上的觸摸事件:onTouchCancel、onTouchEnd、onTouchMove、onTouchStart
②鍵盤類事件:onKeyDown、onKeyPress、onKeyUp
③剪切類事件:onCopy、onCut、onPaste
④表單類:onChange//內(nèi)容變化即觸發(fā)、onInput//輸入框、onSubmit//禁止表單默認跳轉(zhuǎn)行為
⑤事件:onFocus、onBlur
⑥UI元素類:onScroll
⑦鼠標滾動事件:onWheel
⑧鼠標類型:onClick、onContextMenu//右鍵菜單、onDoubleClick //雙擊、onMouseDown、onMouseEnter、onMouseLeave、onMouseMove、onMouseOut、onMouseOver、onMouseUp
⑨拖拽事件:onDrop、onDrag、onDragEnd、onDragEnter、onDragExit、onDragLeave、onDragOver、onDragStart
事件對象介紹
使用方法:就是在編寫事件對象處理函數(shù)的時候,添加一個參數(shù)。拿到這個對象之后,就通過對象的屬性來可以獲取一些信息。
例如:
handleChange:function(event){ console.log(event.target.value); }
示例中,event就是事件對象,event.target就是事件對象的屬性,就是對應(yīng)的DOM元素,拿到這個元素之后再獲取它的值。
事件對象屬性
通用屬性:
其他不同類型的事件有不同的屬性,簡單了解一下
知道了事件的一些屬性,我們就可以很方便地在React中獲取這些屬性,進行一些邏輯的處理,實現(xiàn)一些復(fù)雜的業(yè)務(wù)功能、頁面效果等。
例如:我們可以利用鼠標事件屬性,實時顯示鼠標在某個區(qū)域的坐標:
<script type="text/jsx"> var HelloWorld = React.createClass({ getInitialState: function () { return { x: 0, y: 0 } }, handleMouseMove: function (event) { this.setState({ x: event.clientX, y: event.clientY }); }, render: function () { return <div onMouseMove={this.handleMouseMove} style={{ height: '500px', width: '500px', backgroundColor: 'gray' }}> {this.state.x + ', ' + this.state.y} </div>; }, }); React.render(<HelloWorld></HelloWorld>, document.body); </script>
x組件協(xié)同使用的定義:組件的協(xié)同本質(zhì)上就是對組件的一種組織、管理方式。
組件協(xié)同使用的目的:邏輯清晰、代碼模塊化、封裝細節(jié)、代碼可復(fù)用。
組件協(xié)同使用的方式:
①組件嵌套使用:也就是說,用一個父組件把子組件包裹起來,本質(zhì)就是父子關(guān)系。如下圖描述:
實例代碼:
var React = require('react'); var CommentList=require('./CommentList.jsx'); var CommentForm=require('./commentFrom.jsx'); var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList /> //這是一個組件 <CommentForm /> //這是另一個組件 </div> ); } }); module.exports = CommentBox;
父子組件之間的通信:
父組件->子組件:通過屬性,父組件把數(shù)據(jù)通過屬性來傳遞給子組件
子組件->父組件:本質(zhì)上,子組件不能向父組件通信。但是可以間接地通過觸發(fā)事件來通信,也就是委托。
嵌套組合缺點:
父子關(guān)系的具體實現(xiàn)需要經(jīng)過深思熟慮,貿(mào)然編寫將導(dǎo)致關(guān)系混亂、代碼難以維護
無法掌握所有細節(jié),使用者只知道組件用法,不知道實現(xiàn)細節(jié),遇到問題難以修復(fù)
②Mixin:也就是可以把相同的代碼抽象出來,封裝成一個函數(shù),然后再調(diào)用。
Mixin的目的:橫向抽離出組件的相似代碼
相似概念:面向切向面編程、插件
實例代碼:
var Time=React.createClass({ mixins:[IntervalMixin(1000)], getInitialState:function(){ return {secondElapsed:0}; }, onTick:function(){ this.setState({secondElapsed:this.state.secondElapsed+1}); }, render:function(){ return ( <div>Seconds Elapsed:{this.state.secondsElapsed}</div> ); } });
mixin相當(dāng)簡單,它們就是混合進組件類中的對象而已。React在這方面實現(xiàn)得更加深入,它能防止靜默函數(shù)覆蓋,同時還支持多個mixin混合。但是這些功能在別的系統(tǒng)中可能引起沖突。例如:
React.createClass({ mixins:[{ getInitialState:function(){ return {a:1}} }], getInitialState:function(){ return {b:2}} });
這樣在mixin和組件類中同時定義了getInitialState方法,得到的初始state是{a:1,b:2}.如果mixin中的方法和組件類中的方法返回的對象中存在重復(fù)的鍵,React會拋出一個錯誤來警示這個問題。
六、React中的雙向綁定
React創(chuàng)立的理念跟angular那些框架就是不同的,React是單向數(shù)據(jù)綁定的。那么怎么實現(xiàn)像angular那樣的雙向綁定效果呢?看代碼:
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title>React中的雙向數(shù)據(jù)綁定</title> </head> <body> <script src="./react-0.13.2/react-0.13.2/build/react-with-addons.js"></script> <script src="./react-0.13.2/react-0.13.2/build/JSXTransformer.js"></script> <script type="text/jsx"> var BindingMixin = { handleChange: function(key) { var that = this var newState = {} return function(event) { newState[key] = event.target.value that.setState(newState) } } } var BindingExample = React.createClass({ mixins: [React.addons.LinkedStateMixin], getInitialState: function() { return { text: '', comment: '', } }, render: function() { return <div> <input type="text" placeholder="請輸入內(nèi)容" valueLink={this.linkState('text')} /> <textarea valueLink={this.linkState('comment')}></textarea> <h3>{this.state.text}</h3> <h3>{this.state.comment}</h3> </div> } }) React.render(<BindingExample></BindingExample>, document.body); </script> </body> </html>
效果圖(沒有CSS樣式,有點不優(yōu)雅,見諒):
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助。
相關(guān)文章
React實現(xiàn)單向數(shù)據(jù)流的方法
本文主要介紹了React實現(xiàn)單向數(shù)據(jù)流的方法2023-04-04react循環(huán)數(shù)據(jù)(列表)的實現(xiàn)
這篇文章主要介紹了react循環(huán)數(shù)據(jù)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04react render props模式實現(xiàn)組件復(fù)用示例
本文主要介紹了react render props模式實現(xiàn)組件復(fù)用示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07