React之父子組件傳遞和其它一些要點

react是R系技術棧中最基礎同時也是最核心的一環,2年不到獲取了62.5k star(截止到目前),足可見其給力程度。下面對一些react平常開發中的注意事項進行羅列。html

React的組件生命週期

react主要思想是構建可複用組件來構建用戶界面。在react裏面一切皆組件。每一個組件裏面都是有本身的生命週期,這個生命週期規定了組件的狀態和方法,分別在哪一個階段執行。下面附上一張React的生命週期圖: react

組件第一階段:初始化、渲染以及裝載完成; git

組件第二階段:組件運行時候的狀態 ①:狀態變化引起組件的更新和從新渲染到更新完成 github

                   ②:父組件屬性變化引起組件的更新(是常見的組件之間傳遞數據和同步狀態的手段):好比父組件登陸了,子組件也需變成登陸狀態ide

組件第三階段:卸載組件函數

JSX 語法

const names = ['Alice', 'Emily', 'Kate']; ReactDOM.render( <div> { names.map((name) => { return <div>Hello, {name}!</div>
 }) } </div>,
  document.getElementById('example') );

JSX 的基本語法規則:遇到 HTML 標籤(以 < 開頭),就用 HTML 規則解析;遇到代碼塊(以 { 開頭),就用 JavaScript 規則解析。this

因此給jsx添加註釋只要這樣子:spa

{/* 。。。 */}

父組件傳向子組件

子:
var
HelloMessage = React.createClass({ render: function() { return <h1>Hello {this.props.name}</h1>; } }); ---------------------------------------
父: ReactDOM.render(
<HelloMessage name="Muyy" />, document.getElementById('example') );

變量 HelloMessage 就是至關於一個子組件類。經過this.props.name獲取到了Muyy。3d

另外注意code

  1. 全部組件類都必須有本身的 render 方法,用於輸出組件。
  2. 組件類的第一個字母必須大寫,不然會報錯,好比HelloMessage不能寫成helloMessage
  3. 組件類只能包含一個頂層標籤
  4. class 屬性須要寫成 className ,for 屬性須要寫成 htmlFor ,這是由於 class 和 for 是 JavaScript 的保留字

子組件傳向父(爺)組件

其實很簡單,歸納起來就是:react中state改變了,組件纔會update。父組件寫好state和處理該state的函數,同時將函數名經過props屬性值的形式傳入子,子調用父的函數,同時引發state變化。

例子1.這裏以下圖,用戶郵箱爲父,綠色框爲子。 父組件爲用戶輸入的郵箱設好state,即「{email: ''}」,同時寫好處理state的函數,即「handleEmail」,這兩個名稱隨意起;再將函數以props的形式傳到子組件,子組件只需在事件發生時,調用父組件傳過來的函數便可。 

 1 //子組件
 2 var Child = React.createClass({
 3     render: function(){
 4         return (
 5             <div>
 6                 請輸入郵箱:<input onChange={this.props.handleEmail}/>
 7             </div>
 8         )
 9     }
10 });
11 //父組件,此處經過event.target.value獲取子組件的值
12 var Parent = React.createClass({
13     getInitialState: function(){
14         return {
15             email: ''
16         }
17     },
18     handleEmail: function(event){
19         this.setState({email: event.target.value});
20     },
21     render: function(){
22         return (
23             <div>
24                 <div>用戶郵箱:{this.state.email}</div>
25                 <Child name="email" handleEmail={this.handleEmail.bind(this)}/>
26             </div>
27         )
28     }
29 });
30 React.render(
31   <Parent />,
32   document.getElementById('test')
33 );
demo1 

例子2.有時候每每須要對數據作處理,再傳給父組件,好比過濾或者自動補全等等,下面的例子對用戶輸入的郵箱作簡單驗證,自動過濾非數字、字母和"@."之外的字符。

 1 //子組件,handleVal函數處理用戶輸入的字符,再傳給父組件的handelEmail函數
 2 var Child = React.createClass({
 3     handleVal: function() {
 4         var val = this.refs.emailDom.value;
 5         val = val.replace(/[^0-9|a-z|\@|\.]/ig,"");
 6         this.props.handleEmail(val);
 7     },
 8     render: function(){
 9         return (
10             <div>
11                 請輸入郵箱:<input ref="emailDom" onChange={this.handleVal}/>
12             </div>
13         )
14     }
15 });
16 //父組件,經過handleEmail接受到的參數,即子組件的值
17 var Parent = React.createClass({
18     getInitialState: function(){
19         return {
20             email: ''
21         }
22     },
23     handleEmail: function(val){
24         this.setState({email: val});
25     },
26     render: function(){
27         return (
28             <div>
29                 <div>用戶郵箱:{this.state.email}</div>
30                 <Child name="email" handleEmail={this.handleEmail.bind(this)}/>
31             </div>
32         )
33     }
34 });
35 React.render(
36   <Parent />,
37   document.getElementById('test')
38 );
demo2 

例子3.若是還存在孫子組件的狀況呢?以下圖,黑框爲父,綠框爲子,紅框爲孫,要求子孫的數據都傳給爺爺。原理同樣的,只是父要將爺爺對孫子的處理函數直接傳下去。

 1 //孫子,將下拉選項的值傳給爺爺
 2 var Grandson = React.createClass({
 3     render: function(){
 4         return (
 5             <div>性別:
 6                 <select onChange={this.props.handleSelect}>
 7                     <option value="男">男</option>
 8                     <option value="女">女</option>
 9                 </select>
10             </div>
11         )
12     }
13 });
14 //子,將用戶輸入的姓名傳給爹  
15 //對於孫子的處理函數,父只需用props傳下去便可
16 var Child = React.createClass({
17     render: function(){
18         return (
19             <div>
20                 姓名:<input onChange={this.props.handleVal}/>
21                 <Grandson handleSelect={this.props.handleSelect}/>
22             </div>
23         )
24     }
25 });
26 //父組件,準備了兩個state,username和sex用來接收子孫傳過來的值,對應兩個函數handleVal和handleSelect
27 var Parent = React.createClass({
28     getInitialState: function(){
29         return {
30             username: '',
31             sex: ''
32         }
33     },
34     handleVal: function(event){
35         this.setState({username: event.target.value});
36     },
37     handleSelect: function(event) {
38         this.setState({sex: event.target.value});
39     },
40     render: function(){
41         return (
42             <div>
43                 <div>用戶姓名:{this.state.username}</div>
44                 <div>用戶性別:{this.state.sex}</div>
45                 <Child handleVal={this.handleVal.bind(this)} handleSelect={this.handleSelect.bind(this)}/>
46             </div>
47         )
48     }
49 });
50 React.render(
51   <Parent />,
52   document.getElementById('test')
53 );
demo3

getDefaultProps && getInitialState

getDefaultProps 方法能夠用來設置組件屬性的默認值

var MyTitle = React.createClass({
  getDefaultProps : function () {
    return {
      title : 'Hello World'
    };
  },

  render: function() {
     return <h1> {this.props.title} </h1>;
   }
});

ReactDOM.render(
  <MyTitle />,
  document.body
); 

getInitialState 方法能夠用來設置初始狀態

  getInitialState: function() {
    return {liked: false};
  },

獲取真實的DOM節點

從組件獲取真實 DOM 的節點,這時就要用到 ref 屬性

var MyComponent = React.createClass({
  handleClick: function() {
    this.refs.myTextInput.focus();
  },
  render: function() {
    return (
      <div>
        <input type="text" ref="myTextInput" />
        <input type="button" value="Focus the text input" onClick={this.handleClick} />
      </div>
    );
  }
});

ReactDOM.render(
  <MyComponent />,
  document.getElementById('example')
);

上面代碼中,組件 MyComponent 的子節點有一個文本輸入框,用於獲取用戶的輸入。這時就必須獲取真實的 DOM 節點,虛擬 DOM 是拿不到用戶輸入的。爲了作到這一點,文本輸入框必須有一個 ref 屬性,而後 this.refs.[refName] 就會返回這個真實的 DOM 節點。

須要注意的是,因爲 this.refs.[refName] 屬性獲取的是真實 DOM ,因此必須等到虛擬 DOM 插入文檔之後,才能使用這個屬性,不然會報錯。上面代碼中,經過爲組件指定 Click 事件的回調函數,確保了只有等到真實 DOM 發生 Click 事件以後,纔會讀取 this.refs.[refName] 屬性。

React 組件支持不少事件,除了 Click 事件之外,還有 KeyDown 、CopyScroll 等,完整的事件清單請查看官方文檔

子組件傳向父組件的另外一種思路

父組件調用子組件的state、function,除了上面介紹的方法以外,也能夠經過ref屬性實現。推薦使用這種方式進行子組件向父組件的傳遞。舉個簡單的示範:

export default class 父組件a extends React.Component {
    constructor(props) {
       super(props)   
    }

    render() {
       return (
          <子組件b
               ref={r => this.bbbb =r}  // bbbb自定義名字
          />
       )
    }
}

 

通過這樣處理後後,如今父組件a中能夠經過this.bbbb.state.xxx獲取子組件的xxx狀態,也能夠經過this.bbbb.xxx獲取子組件的xxx方法。

相關文章
相關標籤/搜索