React簡介javascript
是由Facebook公司推廣的一套框架,已經應用instagram等產品css
React就是爲了提供應用程序性能而設計的一套框架html
在angular中,對dom提供了一些指令,讓dom具備一些功能,例如ng-repeat讓dom具備動態循環渲染的功能,ng-show讓dom元素具備動態顯隱的功能等等java
好比將頁面比做一輛汽車,react
Angular的實現就是爲汽車添加一些裝飾,增長一些功能,讓汽車看上去很高大尚,這樣勢必要加大油門jquery
React的實現就是從新制造一輛汽車,是有四個軲轆,便可啓動,不要很大的油門web
React有三大創新json
虛擬dom數組
組件開發瀏覽器
多端適配
一處開發,到處適用
react在0.13版本以後,作了一個處理
將react文件分紅了兩個部分
React.js核心庫文件(建立虛擬dom的,核心模塊,寫的應用程序能夠兼容全部端)
React-dom.js在瀏覽器端渲染虛擬dom
由react對象提供的一個方法createElement
第一個參數表示虛擬dom的名稱,例如div
有時咱們還能夠傳遞組件
第二個參數是一個對象,表示虛擬dom中擁有的屬性
從第三個參數開始表示該虛擬dom元素的子元素
子元素也要由createElement建立,可是文本節點能夠直接寫
方法的返回值是一個虛擬dom(js對象)
由ReactDOM提供的一個方法
三個參數
1 渲染虛擬dom元素
2 真實的dom元素
3 渲染完成回調函數(不經常使用)
1// 建立虛擬dom 2var h1 = React.createElement( 3 'h1', 4 { 5 title: '這是標題' 6 }, 7 '我是文本內容啦啦啦' 8 ) 9// 將h1渲染到頁面中 10ReactDOM.render(h1, document.getElementById('app'), function () { 11 console.log(arguments) 12 console.log(this) })
在react中定義的一個虛擬dom很難複用,因此一般咱們將一組虛擬dom定義在組件中來複用
createClass能夠用來建立一個組件
參數是一個對象,用來描述組件的
能夠在對象中定義render方法,經過返回值來渲染這組組件
返回值,一般全部虛擬dom都在一個容器內
組件式一個類,所以組件名稱要以大寫字母開頭
組件要想渲染到頁面中,就要將組件轉化成虛擬dom,經過React.createElement方法(由React-dom.js提供)
1var List = React.createClass({ 2 // 經過render渲染頁面 3 render: function () { 4 return ( 5 React.createElement( 6 'ul', 7 null, 8 React.createElement('li', null, '六間房秀場'), 9 React.createElement('li', null, '鬥魚TV'), 10 React.createElement('li', null, '美女秀場'), 11 React.createElement('li', null, '秀色直播') 12 ) 13 ) 14 } 15}) 16// 將組件渲染到頁面中 17// 轉化組件到虛擬DOM 18var ul = React.createElement(List) ReactDOM.render(ul, document.getElementById('app'))
咱們寫虛擬dom的最大問題,建立一個虛擬dom成本過高了(寫的太麻煩了),React團隊爲了簡化對createElement的書寫,爲咱們提供了jsx語法
react團隊提供了兩種處理方法
第一種,在瀏覽器端編譯
引入編譯庫,例如browser.js能夠對jsx語法編譯
此時定義的script標籤的type類型要定義成text/babel, 在裏面能夠寫jsx語法
第二種,在工程化中編譯(最多見的)
編譯jsx語法,跟之前編譯less,sass,stylus很像
首先要獲取這些jsx文件(一般咱們將寫jsx語法的文件拓展名改爲.jsx)
以fis爲例
1fis.match('**.jsx', { 2 // 編譯 3 parser: 'babel2', 4 // 更改後綴名稱 5 rExt: '.js' })
Class
Class在js中是保留字,所以在react定義虛擬dom的時候,將class寫成className
For (是label元素特有的屬性)
For是js中的關鍵字,所以在react定義虛擬dom的時候,將for屬性寫成htmlFor
1var h1 = (<h1 className="red">我是文本內容啦啦啦</h1>); 2// 將虛擬dom渲染到頁面中 3ReactDOM.render(h1, document.getElementById('app')) 4 5// 建立一個組件 6var User = React.createClass({ 7 render: function() { 8 // 返回虛擬dom 9 return ( 10 <div> 11 <label htmlFor="user_name">用戶名</label> 12 <input id="user_name" type="text" /> 13 </div> 14 ); 15 } })
React支持插值語法,咱們在jsx語法中使用,語法是 {}
一對{}提供了一個js環境,所以咱們能夠在大括號裏面設置虛擬dom元素的屬性,設置虛擬dom元素的內容
咱們能夠在插值符號中使用js中的任何表達式
Key 爲列表元素定義react-id,綁定id。這樣能夠方便獲取頁面中哪些元素更新了,哪些元素須要更新
Render方法的做用域是組件實例化對象,能夠訪問到組件中定義的方法
1createChildList: function () { 2 // 遍歷數組,處理每個成員,而後映射一個新數組,就是map方法 3 return data.map(function (value, index) { 4 // 每個li要綁定內容,還要設置key 5 return <li key={index}>{value}</li>; 6 }) },
在html中,對於同一類元素來講,之因此展示的樣式不同,是由於他們具備不一樣的屬性,因此屬性可讓同一類元素展示出不一樣的狀態
一樣的道理,在react中,對於同一個組件來講,能夠建立一組虛擬dom樹,若是想讓虛擬dom樹展示出不一樣的狀態,咱們就要爲其添加屬性
在虛擬dom上添加屬性跟在html中元素上添加屬性是同樣的,經過添加一個屬性實現(只不過在組件上添加的都是自定義屬性)
咱們添加的自定義屬性,會存儲在組件的props屬性中,咱們經過this.props能夠訪問到裏面的數據
組件的默認屬性咱們定義在getDefaultProps中,經過返回值設置默認屬性數據
1// 建立導航標題組件 2var Nav = React.createClass({ 3 // 定義默認屬性數據 4 getDefaultProps: function () { 5 // 經過返回值定義默認屬性數據 6 return { 7 data: ['默認標題'] 8 } 9 }, 10 // 封裝渲染內容的方法 11 createChildList: function () { 12 var me = this; 13 // 遍歷this.props.data渲染 14 return this.props.data.map(function (value, index) { 15 return (<a href="" key={index}>{value}{index != me.props.data.length - 1 ? '/' : ''}</a>) 16 }) 17 }, 18 // 經過render方法渲染虛擬dom樹 19 render: function () { 20 return ( 21 <div> 22 {this.createChildList()} 23 </div> 24 ) 25 } 26}) 27var data1 = ['財經', '證券', '理財']; 28// 渲染 ReactDOM.render(<Nav data={data1} />, document.getElementById('app'))
在虛擬dom中咱們能夠爲元素定義樣式
在react中,虛擬dom上不能使用行內樣式字符串,行內樣式只能定義成對象,Css屬性名稱若是出現多個單詞,要使用駝峯式命名,例如
border-color => borderColor
還要求瀏覽器前綴第一個字母要大寫,例如
-webkit-box-shadow => WebkitBoxShadow
在createElement方法中,樣式寫在style中,直接賦值對象,在jsx語法中,樣式寫在style中,要使用插值語法
1// 定義虛擬dom 2var h1 = React.createElement('h1', { 3 style: { 4 color: 'red', 5 fontSize: '40px' 6 } 7}, '我是文本內容啦啦啦'); 8 9// jsx語法,定義虛擬dom 10var h1 = (<h1 style={{ 11 color: 'green', 12 fontSize: '100px' }}>文本內容</h1>)
React中定義事件,跟在html中定義事件很像
在html中定義事件
<button onclick="console.log('hello')">按鈕</button>
在react中jsx語法中定義事件,跟html中定義事件很像
<button onClick={this.clickBtn}>按鈕</button>
on+事件名稱=回調函數
事件名稱首字母大寫
事件回調函數一般綁定組件中的方法
事件回調函數不要執行(後面不要加())
事件回調函數
做用域是組件實例化對象(能夠經過this訪問組件上的方法以及屬性數據)
能夠經過bind方法更改做用域
能夠經過bind方法傳遞自定義參數(不多用)
參數有三個
React封裝的事件對象(最經常使用)
React-id
源生的事件對象
1var Demo = React.createClass({ 2 // 定義事件回調函數 3 clickBtn: function () { 4 console.log(arguments) 5 console.log(this) 6 }, 7 render: function () { 8 return ( 9 <div> 10 <button onClick={this.clickBtn.bind(this, 11)}>這是個按鈕</button> 11 </div> 12 ) 13 } })
這個就是參數
狀態跟屬性同樣都是在組件內部存儲數據的
屬性是組件外部傳遞的數據
狀態是組件內部維護的數據
有狀態組件以及無狀態組件
無狀態組件
對於一個組件來講,若是組件沒有狀態,也就是說組件式一成不變的,組件在建立以後,不會發生交互,請求數據等等,這類組件叫無狀態組件,
組件自身不會維護狀態
有狀態組件
對於一個組件來講,自從建立之後,組件會產生一些交互,請求一些數據,來完成自身狀態的更新,這類組件內部必須維護一個狀態來存儲這些變化的數據,這類組件叫有狀態
組件處於哪一種狀態由其自身存儲的數據決定,組件的存儲跟屬性同樣,在組件實例化對象中有個state屬性,就是用來存儲狀態數據
初始化狀態用getInitialState方法定義,經過return 將初始化狀態的數據返回
修改狀態,用setState方法
參數是一個對象,對象中的屬性就是即將修改的狀態
狀態或者屬性的改變都會觸發render方法的執行,這句話很重要
<html lang="en"> <head> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" type="text/css" href="less/15.less"> </head> <body> <div id="app"></div> <script type="text/javascript" src="lib/react.js"></script> <script type="text/javascript" src="lib/react-dom.js"></script> <script type="text/javascript" src="lib/jquery.js"></script> <script type="text/javascript" src="code/15.jsx"></script> </body> </html>
* { list-style: none; margin: 0; padding: 0; } body { background-repeat: no-repeat; background-attachment: fixed; background-position: center 0; background-size: cover; } #app { width: 1118px; margin: 50px auto; ul { margin-right: -10px; } li { width: 178px; margin-right: 10px; float: left; margin-bottom: 10px; } p { line-height: 30px; text-align: center; } img { cursor: pointer; } }
// 定義換膚組件 var Skin = React.createClass({ // 初始化狀態數據 getInitialState: function () { return { list: [] } }, // 定義事件回調函數 chooseImage: function (e) { // 獲取li元素 var li = e.currentTarget; // 獲取 var id = li.getAttribute('data-id') // 用id獲取大圖片的地址,渲染body document.body.style.backgroundImage = 'url(img/skin/big_' + id + '.jpg)' // console.log(id) }, // 定義渲染列表的方法 getImageList: function () { var me = this; // 經過狀態來渲染了 return this.state.list.map(function (obj, index) { return (<li key={index} data-id={obj.id} onClick={me.chooseImage}> <img src={"img/skin/" + obj.src} alt=""/> <p>{obj.title}</p> </li>) }) }, render: function () { return ( <ul>{this.getImageList()}</ul> ) }, // 發送請求獲取數據 componentDidMount: function () { var me = this; $.get('data/skin.json', function (res) { // 請求成功,更新狀態數據 if (res && res.errno === 0) { me.setState({ list: res.data }) } }) } }) // 渲染到頁面中 ReactDOM.render(<Skin />, document.getElementById('app'))