日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

client高性能组件化框架React简单介绍、特点、环境搭建及经常使用语法

發(fā)布時間:2025/3/20 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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配置文件

module.exports = {entry: {index: './src/js/entry.js'},output: {path: './static/dist/',publicPath: 'http://localhost:8080/static/dist/',filename: '[name].js'},module: {loaders: [{test: /\.js$/,loader: 'babel',query: {presets: ['react', 'es2015']}},{test: /.less$/,loader: 'style!css!less'}]} }

這里的關鍵就是除了要安裝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語法是個神馬東西
可能一會兒大家會看大不明覺厲的代碼
比方

return (<div>hehe<div> )

這就是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的語法了)

var React = require('react'); var ReactDom = require('react-dom');

ReactDom.render()是react最最基本的方法
所以我放到最開始來講
它通過ReactDom將我們的組件渲染到頁面
我在頁面中加入一個節(jié)點

<div id="root"></div>

如今頁面中什么也沒有
只是立即就有了

ReactDom.render(<h1>Demo</h1>,document.getElementById('demo') );

第一個參數是要插入的組件(只是這里我們先插入一個DOM節(jié)點)
第二個參數就是要渲染的DOM節(jié)點
(React不建議直接加入到body標簽document.body,不相信的話能夠試一下會警告)

頁面中出現了“Demo”

實際上react將我們的節(jié)點插入到了div節(jié)點的內部

組件化

React的一大特點就是組件化
React組件Component有以下特點

  • 組合:簡單組件可組合為復雜組件
  • 重用:組件獨立,可被多個組件使用
  • 測試:組件獨立,便于測試
  • 維護:UI和組件相關邏輯都封裝在組件內部,便于維護

組件生成

React.createClass()就是用于將代碼封裝成組件的方法
它會生成一個React組件

var App = React.createClass({render: function(){return (<p>This is a component...</p>)} });

這種方法參數是一個對象
對象中有一個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( )

ReactDom.render(<App></App>,document.getElementById('root') );

組件要寫成標簽的形式
這里我們就要寫<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對象獲取

var App = React.createClass({render: function(){return <p>name:{this.props.name} age:{this.props.age}</p>;} }); ReactDom.render(<App name="payen" age="20"></App>,document.getElementById('root') );


了解了這個,我們能夠做一個小練習
如今有一組數據,利用它組成一個有序列表組件

var data = ['Mr.A','Mr.B','Mr.C'];

能夠將這個數組成為組件屬性
然后利用this.props.data獲取數據
最后使用ES5數組的map方法就大功告成了

var List = React.createClass({render: function(){return (<ol>{this.props.data.map(function(item, index){return <li key={1000 + index}>{item}</li>;})}</ol>) } }); ReactDom.render(<List data={data}></List>,document.getElementById('root') );

還要注意<li key={1000 + index}>{item}</li>
key值假設不寫的話,盡管能夠正常渲染
但會警告我們數組或迭代器的每一項都應該有一個獨一無二的key值

這里我就使用了1000加上索引的形式加入了key值

this.props.children

通常組件的屬性與this.props對象中的屬性是一一相應的
但有一個例外,它是this.props.children
它表示我們組件的全部子節(jié)點
什么意思呢?接著我們上面的樣例
我們在List組件中加入一些子節(jié)點
改動ReactDom.render( )方法的參數

ReactDom.render(<List data={data}><span>Mr.D</span><span>Mr.E</span></List>,document.getElementById('root') );

我們發(fā)現頁面中并沒有什么變化。但瀏覽器也沒有報錯
這時我們須要使用this.props.children

var data = ['Mr.A','Mr.B','Mr.C']; var List = React.createClass({render: function(){console.log(this.props.children);return (<ol>{this.props.data.map(function(item, index){return <li key={1000 + index}>{item}</li>;})}{this.props.children}</ol>) } }); ReactDom.render(<List data={data}><span>Mr.D</span><span>Mr.E</span></List>,document.getElementById('root') );

如此頁面中就顯示出了子節(jié)點

這個this.props.children非常奇怪,它有三種類型值

  • 沒有子節(jié)點,值為undefined
  • 有一個子節(jié)點。值為object對象
  • 有多個子節(jié)點,值為array數組

(能夠在控制臺上輸出驗證)
所以我們處理它要特別小心
好在我們能夠使用React給我們提供的方法
利用React.Children.map( )我們就能夠放心遍歷處理子節(jié)點

var data = ['Mr.A','Mr.B','Mr.C']; var List = React.createClass({render: function(){return (<ol>{this.props.data.map(function(item, index){return <li key={1000 + index}>{item}</li>;})}{React.Children.map(this.props.children,function(child){return <li>{child}</li>})}</ol>) } }); ReactDom.render(<List data={data}><span>Mr.D</span><span>Mr.E</span></List>,document.getElementById('root') );


組件驗證

組件的屬性能夠接受不論什么值。數字、字符串、函數、對象什么都能夠
但有時候,我們拿到一個組件,想要驗證參數是否符合我們的要求(這事實上非常重要。不要藐視)
這時就須要使用組件的propTypes( )方法和React.PropTypes配合驗證了

var data = ['Mr.A','Mr.B','Mr.C']; var App = React.createClass({propTypes: {data: React.PropTypes.array},render: function(){return (<div>{this.props.data}</div>)} }); ReactDom.render(<App data={data}></App>,document.getElementById('root') );

這里我期望的data屬性值為array數組類型
沒有不論什么問題,由于我們傳入的就是數組
可是假設改成期望字符串類型data: React.PropTypes.string

瀏覽器就會發(fā)出警告

具體見React中文官網:Prop 驗證

組件嵌套

還記得React單向數據流的特點么
也就是說我們應該把數據傳遞給父節(jié)點
父節(jié)點通過this.prop將數據傳遞給子節(jié)點
子節(jié)點再通過自己的this.prop處理收到的數據

var data = ['Mr.A','Mr.B','Mr.C']; var List = React.createClass({render: function(){return (<ol>{this.props.data.map(function(item, index){return <li key={1000 + index}>{item}</li>; })}</ol>) } }); var App = React.createClass({render: function(){return (<div><List data={this.props.data}></List></div>)} }); ReactDom.render(<App data={data}></App>,document.getElementById('root') );

所呈現的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( )
      • 首次渲染前調用??勺鲆恍I(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的輸出
    • componentDidMount( )(server端不會調用)
      • 真實DOM被渲染后調用,可通過this.getDOMNode()訪問到真實的DOM元素
        此時可使用其它類庫來操作該DOM
  • 組件存在期Updateing【組件更新時觸發(fā)】(state,props變化觸發(fā))
    • componentWillReceiveProps( )*
      • 組件接收新props時調用,并將其作為參數nextProps使用,此時能夠更改組件props及state
    • shouldComponentUpdate( )*
      • 組件是否應當渲染新props或state
        返回false表示跳過興許生命周期方法(通常不須要使用以避免出現bug)
        在出現應用瓶頸時,可通過該方法進行適當的優(yōu)化。
        在首次渲染期間或者調用了forceUpdate方法后,該方法不會被調用
    • componentWillUpdate( )
      • 接收到新props或state后,進行渲染前調用,此時不同意更新props或state
    • render( )
      • 不再贅述
    • componentDidUpdate( )*
      • 完畢渲染新的props或state后調用。此時能夠訪問到新的DOM元素
  • 組件銷毀期Unmounting【組件銷毀時觸發(fā)】
    • componentWillUnmount()*
      • 組件移除前調用,可用于做一些清理工作
        在componentDidMount中加入的全部任務都須要在該方法中撤銷(e.g.定時器、事件監(jiān)聽器等等)


附上一張我盜的圖,幫助大家理解(手動滑稽)

關于這些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)也會隨之改變

var App = React.createClass({getInitialState: function(){return {open: false}},buttonHandler: function(){this.setState({open: true});},render: function(){return (<div><button onClick={this.buttonHandler}>點擊</button><PopUp open={this.state.open}></PopUp></div> )} }); var PopUp = React.createClass({render: function(){var styles = {position: 'absolute',left: '40px',top: '40px',width: '100px',height: '100px',backgroundColor: '#f40'}if(this.props.open){styles.display = 'block';}else{styles.display = 'none';}return (<div className="popup" style={styles}></div>)} }) ReactDom.render(<App/>,document.getElementById('root') );

第一個功能實現了,再來看第二個
點擊彈窗讓其消失
相同子級的顯示與否掌控在父級手里
要向讓子級消失,就必須要改變父級的組件狀態(tài)this.state
所以我們必須要把事件函數綁定在父級
再利用組件屬性this.props將其傳遞給子級
完整代碼例如以下

var App = React.createClass({getInitialState: function(){return {open: false}},buttonHandler: function(){this.setState({open: true});},popupHandler: function(){this.setState({open: false});},render: function(){return (<div><button onClick={this.buttonHandler}>點擊</button><PopUp open={this.state.open} handler={this.popupHandler}></PopUp></div> )} }); var PopUp = React.createClass({render: function(){var styles = {position: 'absolute',left: '40px',top: '40px',width: '100px',height: '100px',backgroundColor: '#f40'}if(this.props.open){styles.display = 'block';}else{styles.display = 'none';}return (<div className="popup" style={styles} onClick={this.props.handler}></div>)} }) ReactDom.render(<App/>,document.getElementById('root') );

用一句話來總結一下,那就是數據都交給父級來管理

獲取真實DOM節(jié)點

我們已經知道了
創(chuàng)建的組件都是虛擬DOM節(jié)點
僅僅有當它渲染到了頁面。才會成為真正的DOM節(jié)點
可是有些時候,我們須要獲取到真正的DOM節(jié)點
這時須要先設置標簽ref屬性,再利用組件的this.refs對象獲取

還是通過一個小樣例來解釋
如今要實現這樣一個功能
在輸入欄中輸入字符并在外部實時輸出
我們要獲取的真實DOM節(jié)點就是input中的輸入字符串
步驟也非常easy,完整代碼例如以下

var Input = React.createClass({getInitialState: function(){return {val: ''}},changeHandler: function(){this.setState({val: this.refs.node.value});},render: function(){return (<div><input type="text" ref="node" onChange={this.changeHandler}/><p>{this.state.val}</p></div>)} }); ReactDom.render(<Input/>,document.getElementById('root') );

我為input標簽設置了ref值為node
能夠把它理解為為這個節(jié)點起了個小名“node”
那么this.refs.node就能夠引用這個真實的節(jié)點<input/>
通過綁定一個change事件
我們的輸入每次改變都會改變組件的狀態(tài)state
state改變。value就會渲染到頁面

獲取真實DOM節(jié)點另一個不經常使用的方法
比方在我們的樣例中能夠把input標簽改成這樣

<input type="text" ref={function(dom){this._node = dom}.bind(this)} onChange={this.changeHandler}/>

向ref屬性中加入一個匿名函數
這個函數的參數就是真實DOM節(jié)點
我們能夠把它保存下來,比方做為組件的_node屬性
不要忘了改變this的指向
事件觸發(fā)函數就能夠通過this._node獲取真正的DOM節(jié)點

changeHandler: function(){this.setState({val: this._node.value}); }

還要注意的一點是
這個真·DOM節(jié)點的獲取
必須要等到虛擬DOM插入文檔以后。才干使用屬性this.refs.[ref-name]
否則會報錯的


==主頁傳送門==

總結

以上是生活随笔為你收集整理的client高性能组件化框架React简单介绍、特点、环境搭建及经常使用语法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。