client高性能组件化框架React简单介绍、特点、环境搭建及经常使用语法
【本文源址:http://blog.csdn.net/q1056843325/article/details/54729657 轉載請加入該地址】
明天就是除夕了
預祝大家新春快樂 [ ]~( ̄▽ ̄)~*
天天飯局搞得我是身心疲憊= =
所以更新比較慢
今天想跟大家分享的就是這個大名鼎鼎的React框架
簡單介紹
React是近兩年非常流行的框架
流行到什么程度呢?
我看了一下Github上的數據
React達到了5w8+的star
在JavaScript中star排名第4
受歡迎程度可見一斑
感興趣的同學。給大家設置一個傳送門:Github-JavaScript-most stars
React并不難。還是挺easy上手的
起源于Facebook內部項目(一個廣告系統)
傳統頁面從server獲取數據。顯示到瀏覽器上,用戶輸入數據傳入server
但隨著數據量增大,越來越難以維護了
Facebook覺得MVC不能滿足他們的擴展需求了(巨大的代碼庫和龐大的組織)
每當須要加入一項新功能或特性時,系統復雜度就呈幾何增長
致使代碼脆弱不堪、不可預測,結果導致他們的MVC正走向崩潰
當系統中有非常多的模型和相應視圖時,其復雜度就會迅速擴大。非常難以理解和調試
總之就是Facebook對市場上全部JS-MVC框架都不愜意。覺得都不適合大規(guī)模應用
就自己寫了一套,用來架設Instagram站點
寫完后用著用著,發(fā)現哎呦這貨還真是不錯。然后就開源了
隨著這幾年的沉淀。React已經變得越來越強大了
值得我們去了解~
MVC
科普一下MVC
MVC是一種軟件架構模式(后端影響到了前端)
MVC就分為M、V、C三部分
- Model(模型):
應用程序中用于處理應用程序數據邏輯的部分,通常負責在數據庫中存取數據 - View(視圖):
應用程序中處理數據顯示的部分,通常根據模型數據創(chuàng)建 - Controller(控制器):
應用程序中處理用戶交互的部分。通常負責從視圖讀取數據,控制用戶輸入,并向模型發(fā)送數據
簡單的理解一下
我們就是user。在頁面中點擊了一個按鈕觸發(fā)了事件
控制器Controller調整數據,模型Model中數據改變
數據改變又會導致視圖View更新
UI的改變反饋呈現給我們user
這里我要特別說明一下,盡管這里介紹了MVC
可是不能說React就是MVC框架
能夠說React是用于構建組件化UI的庫。是一個前端界面開發(fā)工具
它能夠作為MVC中的View視圖部分
框架特點
React它具有以下特點
- 高性能
傳統web頁面操作DOM涉及重繪重排相當耗性能
React 提供了一種不同而又強大的方式來更新Dom(輕量級虛擬Dom——Virtual Dom)。取代直接操作DOM
更新virtual dom時不一定立即影響真實Dom。React會等到事件循環(huán)結束
利用Diff算法。通過當前新Dom表述與之前做比較,計算出最小步驟來更新真實Dom - 組件化
Dom樹上的節(jié)點稱為元素,而虛擬Dom 的節(jié)點稱作組件(可復用性)
(組件的特點以下還會談到) - 可預測性
state屬性包括定義組件所須要的一些數據,當數據發(fā)生變化時。將會調用render重現渲染
React 把組件看成是一個狀態(tài)機(State Machines)
通過與用戶的交互。實現不同狀態(tài),然后渲染 UI。讓用戶界面和數據保持一致 - 單向數據流
數據從父節(jié)點傳遞到子節(jié)點。僅僅須要從父節(jié)點獲取props渲染就可以
(往下看就理解了)
環(huán)境搭建
我選擇使用webpack搭建好開發(fā)環(huán)境。當然其它工具也能夠
這是我的webpack.config.js配置文件
這里的關鍵就是除了要安裝babel-loader和babel-core
還要安裝babel-preset-es2015 和 babel-preset-react
用于解析ES6語法和React的JSX語法
還有react和react-dom也是必須要下載的依賴
全部依賴模塊在這里
"devDependencies": {"babel-core": "^6.22.1","babel-loader": "^6.2.10","babel-preset-es2015": "^6.22.0","babel-preset-react": "^6.22.0","css-loader": "^0.26.1","less": "^2.7.2","less-loader": "^2.2.3","react": "^15.4.2","react-dom": "^15.4.2","style-loader": "^0.13.1","webpack": "^1.14.0","webpack-dev-server": "^1.16.2" }JSX
簡單說一下React的JSX語法是個神馬東西
可能一會兒大家會看大不明覺厲的代碼
比方
這就是JSX代碼,它是React提供的語法糖
是React的重要組成部分,使用相似XML標記的方式來聲明界面及關系
語法糖的意思我寫ES6的時候也說了
就是計算機語言中加入的語法。對語言的功能沒影響
方便我們開發(fā)者使用的,能夠增強可讀性
假設使用JS代碼也能夠,只是官方推薦使用JSX
這樣結構層次關系都非常清晰
webpack會幫我們把他們轉換成瀏覽器認識的js代碼(loader的作用)
(假設好奇轉換成了什么,能夠去webpack輸出文件查看,或者找jsx轉js的工具)
JSX語法結構說的通俗一點就是HTML、JS混寫
可能大家會有疑惑,說好的結構、樣式、行為相分離的前端思想呢?!
React當中一個基本的設計理念是編寫簡單且easy理解的代碼
但我們?yōu)榱藢崿F組件化確實不方便松耦合
大家也不要過分較真
這種語法結構是如何解析的呢?事實上并不奇妙
JSX的語法規(guī)則:
- 遇到 HTML 標簽(以 < 開頭),就使用 HTML 規(guī)則解析
- 遇到代碼塊(以 { 開頭),就使用 JavaScript 規(guī)則解析
- 代碼塊中假設僅僅有一個數組變量,就展開這個數組的全部成員
不理解不要慌。看了以下就懂了
提前滲透一下
渲染到頁面
最終寫到語法正題了
在此之前我們必須要引用的兩個對象
一個React核心對象和一個React-Dom對象
(這里就先不使用ES6的語法了)
ReactDom.render()是react最最基本的方法
所以我放到最開始來講
它通過ReactDom將我們的組件渲染到頁面
我在頁面中加入一個節(jié)點
如今頁面中什么也沒有
只是立即就有了
第一個參數是要插入的組件(只是這里我們先插入一個DOM節(jié)點)
第二個參數就是要渲染的DOM節(jié)點
(React不建議直接加入到body標簽document.body,不相信的話能夠試一下會警告)
頁面中出現了“Demo”
實際上react將我們的節(jié)點插入到了div節(jié)點的內部
組件化
React的一大特點就是組件化
React組件Component有以下特點
- 組合:簡單組件可組合為復雜組件
- 重用:組件獨立,可被多個組件使用
- 測試:組件獨立,便于測試
- 維護:UI和組件相關邏輯都封裝在組件內部,便于維護
組件生成
React.createClass()就是用于將代碼封裝成組件的方法
它會生成一個React組件
這種方法參數是一個對象
對象中有一個render返回一個組件
render是輸出組件必須要寫的(關于它以下還會再說)
先記住兩點
- 組件名首字母一定大寫。否則會報錯
- 輸出的組件僅僅能有一個頂級標簽。其它標簽會失效
所以。各位,以下的寫法都是不正確的
//錯誤的寫法:變量名首字母沒大寫 var app = React.createClass({render: function(){return <p>This is a component...</p>} }) //錯誤的寫法:存在多個頂級標簽 var App = React.createClass({render: function(){return (<p>This is a component...</p><p>This is also a component...</p>)} });組件中html語法兩邊加括號的目的
是為了
防止JavaScript自己主動分號機制產生問題
組件渲染
生成的組件要想渲染到頁面
就使用我們剛剛提到的的ReactDom.render( )
組件要寫成標簽的形式
這里我們就要寫<App></App>或者單標簽形式<App/>也能夠
組件特性
為了加以區(qū)分。我把html標簽的屬性叫組件特性
var App = React.createClass({render: function(){return <p name="demo">This is a component...</p>;} }); ReactDom.render(<App></App>,document.getElementById('root') );還要注意兩個特例
- class要寫成className
- for要寫成htmlFor
由于他們是JavaScript的保留字
假設想要為組件加入內聯樣式,能夠這樣寫
var App = React.createClass({render: function(){var styles = {color: '#fff',backgroundColor: '#000'}return <p className="demo" style={styles}>This is a component...</p>; // <--} }); ReactDom.render(<App></App>,document.getElementById('root') );聲明了一個styles對象
可是將它加入到屬性時。要使用 { }
由于JSX語法中。html中使用js就必須使用大括號
關于這一點以下就不再贅述了
組件屬性
this.props
組件的屬性相同能夠像html一樣加入<App name="payen"></App>
而且這個組件屬性內部能夠通過this.props對象獲取
了解了這個,我們能夠做一個小練習
如今有一組數據,利用它組成一個有序列表組件
能夠將這個數組成為組件屬性
然后利用this.props.data獲取數據
最后使用ES5數組的map方法就大功告成了
還要注意<li key={1000 + index}>{item}</li>
key值假設不寫的話,盡管能夠正常渲染
但會警告我們數組或迭代器的每一項都應該有一個獨一無二的key值
這里我就使用了1000加上索引的形式加入了key值
this.props.children
通常組件的屬性與this.props對象中的屬性是一一相應的
但有一個例外,它是this.props.children
它表示我們組件的全部子節(jié)點
什么意思呢?接著我們上面的樣例
我們在List組件中加入一些子節(jié)點
改動ReactDom.render( )方法的參數
我們發(fā)現頁面中并沒有什么變化。但瀏覽器也沒有報錯
這時我們須要使用this.props.children
如此頁面中就顯示出了子節(jié)點
這個this.props.children非常奇怪,它有三種類型值
- 沒有子節(jié)點,值為undefined
- 有一個子節(jié)點。值為object對象
- 有多個子節(jié)點,值為array數組
(能夠在控制臺上輸出驗證)
所以我們處理它要特別小心
好在我們能夠使用React給我們提供的方法
利用React.Children.map( )我們就能夠放心遍歷處理子節(jié)點
組件驗證
組件的屬性能夠接受不論什么值。數字、字符串、函數、對象什么都能夠
但有時候,我們拿到一個組件,想要驗證參數是否符合我們的要求(這事實上非常重要。不要藐視)
這時就須要使用組件的propTypes( )方法和React.PropTypes配合驗證了
這里我期望的data屬性值為array數組類型
沒有不論什么問題,由于我們傳入的就是數組
可是假設改成期望字符串類型data: React.PropTypes.string
瀏覽器就會發(fā)出警告
具體見React中文官網:Prop 驗證
組件嵌套
還記得React單向數據流的特點么
也就是說我們應該把數據傳遞給父節(jié)點
父節(jié)點通過this.prop將數據傳遞給子節(jié)點
子節(jié)點再通過自己的this.prop處理收到的數據
所呈現的DOM結構
生命周期
生命周期不難理解
組件的一生無非就是產生、更新、銷毀
在組件的每個生命周期內,都會按順序觸發(fā)一些組件方法
比方我們剛剛的render方法就會在產生和更新的階段都會觸發(fā)
具體觸發(fā)的回調函數API以及作用給大家整理在以下
(關于它們在整個生命周期的觸發(fā)次數大家應該都能想明確就不寫了)
(不經常使用的我在后面的標注了*號)
- 組件實例化Mouting【組件生成時觸發(fā)】
- getDefaultProps( )
- 作用于組件類,返回對象用于設置默認的this.props(引用值會在實例中共享)
- e,g.return {name: 'payen'} 相當于初始化了組件屬性this.props.name = 'payen'
- getInitialState( )
- 作用于組件的實例,返回對象作為this.state的初始值
- e,g.return {show: false} 相當于初始化了組件狀態(tài)this.state.show = false
- componentWillMount( )
- 首次渲染前調用。可做一些業(yè)務初始化操作。也能夠通過this.setState()設置組件狀態(tài)
- e,g.this.setState({show: false})
- render( )
- 必選方法,用于創(chuàng)建虛擬DOM,有特殊規(guī)則(再啰嗦一遍)
- 僅僅能通過this.props和this.state訪問數據
- 能夠返回null、false或不論什么React組件
- 僅僅能出現一個頂級組件(不能返回數組)
- 不能改變組件的狀態(tài)
- 不能改動DOM的輸出
- 必選方法,用于創(chuàng)建虛擬DOM,有特殊規(guī)則(再啰嗦一遍)
- componentDidMount( )(server端不會調用)
- 真實DOM被渲染后調用,可通過this.getDOMNode()訪問到真實的DOM元素
此時可使用其它類庫來操作該DOM
- 真實DOM被渲染后調用,可通過this.getDOMNode()訪問到真實的DOM元素
- getDefaultProps( )
- 組件存在期Updateing【組件更新時觸發(fā)】(state,props變化觸發(fā))
- componentWillReceiveProps( )*
- 組件接收新props時調用,并將其作為參數nextProps使用,此時能夠更改組件props及state
- shouldComponentUpdate( )*
- 組件是否應當渲染新props或state
返回false表示跳過興許生命周期方法(通常不須要使用以避免出現bug)
在出現應用瓶頸時,可通過該方法進行適當的優(yōu)化。
在首次渲染期間或者調用了forceUpdate方法后,該方法不會被調用
- 組件是否應當渲染新props或state
- componentWillUpdate( )
- 接收到新props或state后,進行渲染前調用,此時不同意更新props或state
- render( )
- 不再贅述
- componentDidUpdate( )*
- 完畢渲染新的props或state后調用。此時能夠訪問到新的DOM元素
- componentWillReceiveProps( )*
- 組件銷毀期Unmounting【組件銷毀時觸發(fā)】
- componentWillUnmount()*
- 組件移除前調用,可用于做一些清理工作
在componentDidMount中加入的全部任務都須要在該方法中撤銷(e.g.定時器、事件監(jiān)聽器等等)
- 組件移除前調用,可用于做一些清理工作
- componentWillUnmount()*
附上一張我盜的圖,幫助大家理解(手動滑稽)
關于這些API更具體的信息
建議大家能夠去React中文官網查看:Component Specs and Lifecycle
組件狀態(tài)
上面提到了this.state,和我們之前介紹的this.props一樣重要
只是this.props通常不會變。但this.state會變
就如其字面意思,表示組件的狀態(tài)
這個屬性是僅僅讀的
所以設置狀態(tài)我們須要使用this.setState( )
可使用this.setState( )的方法:
componentWillMount、componentDidMount、componentWillReceiveProps
組件交互
在此之前我們須要了解的就是React的事件系統
JavaScript原始行間綁定事件都是普遍小寫<button onclick="clickHandle()"></button>
但我們在React中要使用駝峰寫法<button onClick="clickHandle()"></button>
React的事件處理器會傳入虛擬事件對象的實例(一個對瀏覽器本地事件的跨瀏覽器封裝)
它有和瀏覽器本地事件相同的屬性和方法。包括 stopPropagation() 和 preventDefault(),
可是沒有瀏覽器兼容問題
具體支持事件見中文官網:事件系統-支持的事件
如今我們要來實現這樣一個簡單的功能
點擊按鈕,出現彈框
單擊彈框。彈框消失
先來實現結構與樣式
var App = React.createClass({render: function(){return (<div><button>點擊</button><PopUp></PopUp></div> )} }); var PopUp = React.createClass({render: function(){var styles = {position: 'absolute',left: '40px',top: '40px',width: '100px',height: '100px',backgroundColor: '#f40'}return (<div className="popup" style={styles}></div>)} }) ReactDom.render(<App/>,document.getElementById('root') );首先我們先來實現第一個功能:點擊按鈕出現彈框
問題是改如何實現
我們的React是單向數據流
父級向子級傳遞數據
最好的辦法就是在父級設置組件狀態(tài)this.state
將狀態(tài)通過組件屬性this.props傳遞給子級
這樣點擊事件要做的就是改變父級狀態(tài)
子級狀態(tài)也會隨之改變
第一個功能實現了,再來看第二個
點擊彈窗讓其消失
相同子級的顯示與否掌控在父級手里
要向讓子級消失,就必須要改變父級的組件狀態(tài)this.state
所以我們必須要把事件函數綁定在父級
再利用組件屬性this.props將其傳遞給子級
完整代碼例如以下
用一句話來總結一下,那就是數據都交給父級來管理
獲取真實DOM節(jié)點
我們已經知道了
創(chuàng)建的組件都是虛擬DOM節(jié)點
僅僅有當它渲染到了頁面。才會成為真正的DOM節(jié)點
可是有些時候,我們須要獲取到真正的DOM節(jié)點
這時須要先設置標簽ref屬性,再利用組件的this.refs對象獲取
還是通過一個小樣例來解釋
如今要實現這樣一個功能
在輸入欄中輸入字符并在外部實時輸出
我們要獲取的真實DOM節(jié)點就是input中的輸入字符串
步驟也非常easy,完整代碼例如以下
我為input標簽設置了ref值為node
能夠把它理解為為這個節(jié)點起了個小名“node”
那么this.refs.node就能夠引用這個真實的節(jié)點<input/>
通過綁定一個change事件
我們的輸入每次改變都會改變組件的狀態(tài)state
state改變。value就會渲染到頁面
獲取真實DOM節(jié)點另一個不經常使用的方法
比方在我們的樣例中能夠把input標簽改成這樣
向ref屬性中加入一個匿名函數
這個函數的參數就是真實DOM節(jié)點
我們能夠把它保存下來,比方做為組件的_node屬性
不要忘了改變this的指向
事件觸發(fā)函數就能夠通過this._node獲取真正的DOM節(jié)點
還要注意的一點是
這個真·DOM節(jié)點的獲取
必須要等到虛擬DOM插入文檔以后。才干使用屬性this.refs.[ref-name]
否則會報錯的
==主頁傳送門==
總結
以上是生活随笔為你收集整理的client高性能组件化框架React简单介绍、特点、环境搭建及经常使用语法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Netstat命令(windows下)
- 下一篇: 常用PHP array数组函数