這裡只是對自己的學習進行一次總結,也是為了讓自己以後如果長時間不使用快速記憶起來的筆記,如果想要學習,還是去官網看文檔比較好一些。、 註意 下麵的代碼的 script標簽的type類型都為 “text/babel” 目錄 一、無狀態組件 二、函數式聲明 三、this以及事件對象 四、操作dom元素 ...
這裡只是對自己的學習進行一次總結,也是為了讓自己以後如果長時間不使用快速記憶起來的筆記,如果想要學習,還是去官網看文檔比較好一些。、
註意 下麵的代碼的 script標簽的type類型都為 “text/babel”
目錄
一、 無狀態的組件
只是普通的變數是沒有狀態的, 只有組件才有狀態或無狀態
react是單向數據流
狀態其實就是讓數據驅動視圖的響應式數據
1 let a = '這裡是div元素111'; 2 3 setTimeout(() => { 4 console.log('函數執行了'); 5 a = '改變之後的值' 6 },2000); 7 8 const element = ( 9 <div>{a}</div> 10 ); 11 12 ReactDOM.render( 13 element, 14 document.getElementById('app') 15 )
如果你學習過vue的話,那種雙向數據綁定用的 Object.defineProperty() 叫數據劫持,然後用了訂閱發佈(觀察者)那種模式,數據改變之後,會驅動著視圖去改變
react必須要通過 setState() 這個組件的實例化對象去調用去改變自身的state才會去驅動視圖是改變的,所以上面的那種就算數據改變了,但是視圖是沒有進行改變的。
看下麵的es6的這種寫法
1 class Element extends React.Component{ 2 constructor() { 3 super(); 4 this.state = { // 只有在state裡面的內容才是有無狀態的 5 a: '這裡是div元素' 6 }; 7 8 setTimeout(() => { 9 this.setState({ // 這裡必要要用 setState這個方法來改變值才會驅動視圖去改變 如果 this.state.a = 'sdfsd' 這樣是不會驅動視圖去改變的 10 a: '改變之後的值' 11 }) 12 }, 1000) 13 } 14 render() { 15 return ( 16 <div> 17 {this.state.a} 18 </div> 19 ); 20 } 21 } 22 23 ReactDOM.render( 24 <Element/>, 25 document.getElementById('app') 26 )
二、 函數式聲明
其實之前一直都是使用的變數去指代html元素,沒有使用過 class 那種,現在先使用ES5的寫法去寫一寫什麼是函數式聲明。
先看一下之前的寫法吧
1 const Head = ( 2 <h2>Head頭部</h2> 3 ); 4 const Foot = ( 5 <h2>底部</h2> 6 ); 7 const element = ( 8 <div> 9 { 10 Head 11 } 12 <h2>Element內容</h2> 13 { 14 Foot 15 } 16 </div> 17 ); 18 19 ReactDOM.render( 20 element, 21 document.getElementById('app') 22 )
函數式聲明是什麼樣子的呢
1 const Head = function () { 2 return ( 3 <h2>Head頭部</h2> 4 ) 5 }; 6 const Foot = function () { 7 return ( 8 <h2>底部</h2> 9 ) 10 }; 11 const Element = function() { 12 return ( 13 <div> 14 <Head/> 15 <h2>Element內容</h2> 16 <Foot/> 17 </div> 18 ); 19 }; 20 21 ReactDOM.render( 22 <Element></Element>, 23 document.getElementById('app') 24 )
可以很清晰的看到他們兩個的區別,一個是使用變數來代表的,另外的一個是使用的組件形式代表的,開發中的寫法都是使用ES6的class繼承聲明來寫組件的
看一下函數聲明的傳值
1 const Head = function (props) { 2 return ( 3 <h2>{props.title}</h2> 4 ) 5 }; 6 const Foot = function (props) { 7 return ( 8 <h2>{props.con}</h2> 9 ) 10 }; 11 const Element = function() { 12 return ( 13 <div> 14 <Head 15 title={'頭部信息啊'} 16 /> 17 <h2>Element內容</h2> 18 <Foot 19 con={'底部的內容啊'} 20 /> 21 </div> 22 ); 23 }; 24 25 ReactDOM.render( 26 <Element></Element>, 27 document.getElementById('app') 28 )
這個樣子和vue其實是挺像的,在標簽上面寫自定義的屬性,子組件就可以接收到,等先這樣看看,後面會使用class寫的,class寫起來感覺還容易理解一些。
註意: 函數式聲明組件
1. 組件的首字母必須是大寫
2. 不要使用H5新標簽
下麵看一個狀態改變驅動視圖的例子
1 const Head = function (props) { 2 return ( 3 <h2>{props.title}</h2> 4 ) 5 }; 6 const Foot = function (props) { 7 return ( 8 <h2>{props.con}</h2> 9 ) 10 }; 11 12 class Element extends React.Component{ 13 constructor() { 14 super(); 15 this.state = { 16 title: '頭部信息', 17 con: '底部信息' 18 }; 19 20 setTimeout(() => { 21 this.setState({ 22 title: '頭部信息改變' 23 }) 24 },2000) 25 } 26 render() { 27 return ( 28 <div> 29 <Head 30 title={this.state.title} 31 /> 32 <h2>Element內容</h2> 33 <Foot 34 con={this.state.con} 35 /> 36 </div> 37 ); 38 } 39 } 40 41 ReactDOM.render( 42 <Element></Element>, 43 document.getElementById('app') 44 )
這樣就可以和上面那種結合起來了,以後所有的組件都用class來寫了,就不用function那種形式了。
三、 this以及事件對象
react組件中的this和事件對象的不同寫法有的寫法是需要綁定this的
1 class Element extends React.Component{ 2 constructor() { 3 super(); 4 } 5 6 btn() { 7 console.log(this); // 可以看到這裡列印的是 undefined 8 } 9 10 render() { 11 return ( 12 <div> 13 <h1>title</h1> 14 <button onClick={this.btn}>按鈕</button> 15 </div> 16 ); 17 } 18 } 19 20 ReactDOM.render( 21 <Element></Element>, 22 document.getElementById('app') 23 )
看到上面列印的this是undefined,下麵有幾種寫法可以更正this指向實例化對象的
第一種 更正this和事件對象
1 class Element extends React.Component{ 2 constructor() { 3 super(); 4 this.btn = this.btn.bind(this); // 在這裡更正,官方推薦的也是這種寫法 5 } 6 7 btn(e) { 8 console.log(this); 9 console.log(e.target) 10 } 11 12 render() { 13 return ( 14 <div> 15 <h1>title</h1> 16 <button onClick={this.btn}>按鈕</button> 17 </div> 18 ); 19 } 20 } 21 22 ReactDOM.render( 23 <Element></Element>, 24 document.getElementById('app') 25 )
需要註意的是上面的那種寫法如果傳遞參數的話,那麼事件對象就是最後一個沒有對象參數的和js中的bind一樣
1 class Element extends React.Component{ 2 constructor() { 3 super(); 4 this.btn = this.btn.bind(this); // 在這裡更正,官方推薦的也是這種寫法 5 } 6 7 btn() { 8 console.log(this); 9 console.log(arguments) // 因為下麵的函數傳遞了參數,這裡第二個參數才是事件對象 10 } 11 12 render() { 13 return ( 14 <div> 15 <h1>title</h1> 16 <button onClick={this.btn(1)}>按鈕</button> 17 </div> 18 ); 19 } 20 } 21 22 ReactDOM.render( 23 <Element></Element>, 24 document.getElementById('app') 25 )
第二種 在行內bind
1 class Element extends React.Component{ 2 constructor() { 3 super(); 4 } 5 6 btn() { 7 console.log(this); 8 console.log(arguments) 9 } 10 11 render() { 12 return ( 13 <div> 14 <h1>title</h1> 15 <button onClick={this.btn.bind(this, 1)}>按鈕</button> // 直接寫到行內,在這裡改變this的指向,同樣的問題,那個參數的事件對象是最後一個 16 </div> 17 ); 18 } 19 } 20 21 ReactDOM.render( 22 <Element></Element>, 23 document.getElementById('app') 24 )
第三種 在一個函數裡面執行它
1 class Element extends React.Component{ 2 constructor() { 3 super(); 4 } 5 6 btn(e) { 7 console.log(this); 8 console.log(arguments) 9 } 10 11 render() { 12 return ( 13 <div> 14 <h1>title</h1> 15 <button onClick={(e) => { 16 this.btn(e,11); 17 }}>按鈕</button> 18 </div> 19 ); 20 } 21 } 22 23 ReactDOM.render( 24 <Element></Element>, 25 document.getElementById('app') 26 )
第四種 改變函數的寫法
1 class Element extends React.Component{ 2 constructor() { 3 super(); 4 } 5 6 btn = (e) => { 7 console.log(this); 8 console.log(e.target) 9 } 10 11 render() { 12 return ( 13 <div> 14 <h1>title</h1> 15 <button onClick={this.btn}>按鈕</button> 16 </div> 17 ); 18 } 19 } 20 21 ReactDOM.render( 22 <Element></Element>, 23 document.getElementById('app') 24 )
當然了這種方式如果要傳遞參數的話還是需要bind的。
四、 操作dom元素
如果想要在react中操作dom元素的話,有幾種方法
第一種 直接使用js的方法
1 class Element extends React.Component{ 2 constructor() { 3 super(); 4 5 } 6 7 btn = () => { 8 const ele = document.querySelector('.h1'); 9 console.log(ele); 10 11 }; 12 13 render() { 14 return ( 15 <div> 16 <h1 className='h1'>title</h1> 17 <button onClick={this.btn}>按鈕</button> 18 </div> 19 ); 20 } 21 } 22 23 ReactDOM.render( 24 <Element></Element>, 25 document.getElementById('app') 26 )
第二種 通過事件對象
1 class Element extends React.Component{ 2 constructor() { 3 super(); 4 5 } 6 7 btn = (e) => { 8 console.log(e.target); 9 }; 10 11 render() { 12 return ( 13 <div> 14 <h1 className='h1'>title</h1> 15 <button onClick={this.btn}>按鈕</button> 16 </div> 17 ); 18 } 19 } 20 21 ReactDOM.render( 22 <Element></Element>, 23 document.getElementById('app') 24 )
第三種 ref
和vue一樣
1 class Element extends React.Component{ 2 constructor() { 3 super(); 4 5 } 6 7 btn = (e) => { 8 console.log(this.refs.abc) // 在這裡獲取它 9 }; 10 11 render() { 12 return ( 13 <div> 14 <h1 ref="abc">title</h1> // 這裡定義一個字元串的名字 15 <button onClick={this.btn}>按鈕</button> 16 </div> 17 ); 18 } 19 } 20 21 ReactDOM.render( 22 <Element></Element>, 23 document.getElementById('app') 24 )
不過最新版本的不建議上面的那種寫法了,也是ref建議下麵的寫法
以後我們就可以用下麵這種最常用的方式
1 class Element extends React.Component{ 2 constructor() { 3 super(); 4 5 } 6 7 btn = (e) => { 8 console.log(this.abc) 9 }; 10 11 render() { 12 return ( 13 <div> 14 <h1 ref={abc => {this.abc = abc}}>title</h1> 15 <button onClick={this.btn}>按鈕</button> 16 </div> 17 ); 18 } 19 } 20 21 ReactDOM.render( 22 <Element></Element>, 23 document.getElementById('app') 24 )
第四種 ReactDOM.findDOMNode
1 class Element extends React.Component{ 2 constructor() { 3 super(); 4 5 } 6 7 btn = (e) => { 8 console.log(this.abc) 9 10 console.log(ReactDOM.findDOMNode(this.abc)); 11 }; 12 13 render() { 14 return ( 15 <div> 16 <h1 ref={abc => {this.abc = abc}}>title</h1> 17 <button onClick={this.btn}>按鈕</button> 18 </div> 19 ); 20 } 21 } 22 23 ReactDOM.render( 24 <Element></Element>, 25 document.getElementById('app') 26 )
ref如果標記的是組件,那麼ref他就是組件,但是findDOMNode這種方式是獲取DOM元素的,就算裡面的參數是組件,也是獲得DOM元素
五、 父子組件傳值
核心思想
父組件給子組件傳值 直接在組件上面添加屬性就可以了 子組件通過props訪問,得到 其實是構造函數實例化的時候傳過去了
子組件給父組件傳值 其實是父組件給子組件傳一個函數,子組件調用的時候把 要傳遞的數據 放到 父組件傳遞過來的函數 的參數裡面,然後父組件再去做他自己的操作
Item子組件
1 class Item extends React.Component { 2 constructor (props) { 3 super(props); 4 this.state = { 5 sub: this.props.data 6 } 7 } 8 9 componentWillReceiveProps(nextProps) { 10 console.log('執行了嗎'); 11 console.log(nextProps); 12 } 13 14 render() { 15 console.log('子組件列印this'); 16 console.log(this); 17 console.log(this.props); 18 19 return ( 20 <div> 21 <p>Item組件</p> 22 <h1>{this.state.sub.res}</h1> 23 <input type="button" defaultValue="這裡" onClick={this.props.supFn.bind(this,'子組件參數')} /> 24 <input type="button" 25 defaultValue="22" 26 onClick={() => { 27 this.props.supFn('參數2') 28 }} 29 30 /> 31 </div> 32 ); 33 } 34 }
父組件
1 class Main extends React.Component { 2 constructor() { 3 super(); 4 this.superFn = this.superFn.bind(this); 5 6 } 7 state = { 8 data: { 9 res: '裡面的數據' 10 } 11 }; 12 13 superFn(a) { 14 console.log('父組件的函數'); 15 console.log(`${a}`); 16 let data = { 17 res: '修改過後' 18 }; 19 console.log(data); 20 21 this.setState({ 22 data: data 23 }) 24 } 25 render() { 26 return ( 27 <div> 28 <p>主頁面</p> 29 <p>{this.state.data.res}</p> 30 <Item supFn={this.superFn} data={this.state.data} aaa="傳值啊"></Item> 31 </div> 32 ); 33 } 34 } 35 36 ReactDOM.render( 37 <Main />, 38 document.getElementById('app') 39 )
六、在瀏覽器中支持import export
要在伺服器環境下打開文件
在谷歌瀏覽器輸入框中輸入
然後就可以使用模塊導出導出功能了
1 // 2.js 2 const a = 1; 3 const b = 2; 4 5 export default {a, b};
1 <script type="module"> 2 // 要伺服器環境下打開 http服務 3 // chrome//flags 開啟那個許可權 4 import a from './2.js'; 5 console.log(a) 6 </script>
如果你看了我的文章有了一些收穫我會非常高興的,由於能力有限,文章有的部分解釋的不到位,希望在以後的日子里能慢慢提高自己能力,如果不足之處,還望指正。