React中的數據傳遞
在 react 的學習過程中,少不了會遇到各個組件之間數據傳遞的問題,本文主要是在個人學習做項目過程中,對數據在 react 組件中傳遞的小總結。
數據傳遞的流向:1、數據從父組件傳遞到子組件,2、數據從子組件傳遞到父組件,3、多個組件共享狀態數據。
數據傳遞的方式:1、實例屬性 props,2、函數,3、狀態提升
當然,context 也可以實現組件間的數據傳遞,官網對其的描述為: “使用React可以非常輕松地追蹤通過React組件的數據流,在有些場景中,你不想要向下每層都手動地傳遞你需要的 props. 這就需要強大的 context API了”。但是同樣也提到:“絕大多數應用程序不需要使用 context,如果你想讓你的應用更穩定,別使用context。因為這是一個實驗性的API,在未來的React版本中可能會被更改”。具體使用方法可到官網查看。本文提供代碼和注釋以及運行的結果圖,具體的代碼說明可查看注釋。
數據從父組件到子組件
數據由父組件傳遞到子組件相對簡單,一般的處理方法是,在父組件中定義、獲取需要傳遞的數據,在父組件頁面中通過 <子組件名稱 props屬性名稱 = {傳遞的數據} /> 傳遞,最后在子組件中使用 this.props.props對應的屬性名稱 即可接受父組件傳遞過來的數據。
一、將數據從父組件傳遞到子組件,數據傳遞過程中,注意父組件和子組件中各自屬性的名稱要對應
父組件代碼:
1 var React = require('react');
2 var ReactDOM = require('react-dom'); 3 import BodyChild from './components/indexchild'; 4 5 class Index extends React.Component { 6 7 constructor() { 8 //調用基類的所有的初始化方法 9 super(); 10 11 // 設置當前組件的屬性 12 this.state = { 13 username: "Guang", 14 age: 20 15 }; 16 }; 17 18 parentFunc(){ 19 alert("我是父組件中的 parentFunc 函數"); 20 } 21 22 render() { 23 return ( 24 <div> 25 <h3>父組件</h3> 26 27 {/* 顯示當前組件的屬性作為對照 */} 28 <p>age_parent: {this.state.age}</p> 29 <p>username: {this.state.username}</p> 30 31 <BodyChild 32 //將當前組件的 state.xxx 屬性傳遞給 子組件的 props.xxx_child 33 age_child={this.state.age} 34 username_child={this.state.username} 35 // 將 父組件的函數 this.parentFunc 傳遞給子組件 props.childFunc 36 childFunc={this.parentFunc.bind(this)} 37 /> 38 </div> 39 ); 40 } 41 } 42 43 ReactDOM.render( 44 <Index/>, document.getElementById('example'));
子組件代碼:
1 import React from 'react';
2
3 export default class BodyChild extends React.Component{ 4 5 constructor(props){ 6 // React組件的構造函數將會在裝配之前被調用。當為一個React.Component子類定義構造函數時, 7 // 你應該在任何其他的表達式之前調用super(props)。否則,this.props在構造函數中將是未定義,並可能引發異常 8 super(props); 9 10 // 父組件傳遞過來的屬性存儲在 props.username_child 中,將其賦值給當前組件的 state.username_child 11 this.state={username_child:props.username_child} 12 } 13 14 render(){ 15 return( 16 <div> 17 <h3>子組件</h3> 18 19 {/* 父組件傳遞過來的屬性存儲在 props.age_child 中,獲取並顯示屬性的值 */} 20 <p>age_child(通過 props 獲得): {this.props.age_child}</p> 21 22 {/* 獲取並顯示 state.username_child,該屬性的值是從父組件中獲取的 */} 23 <p>username_child(通過 props 賦值給 state 獲得): {this.state.username_child}</p> 24 25 {/* 這里獲取並執行父組件傳遞過來的函數 */} 26 {this.props.childFunc()} 27 </div> 28 ) 29 } 30 }
運行結果:

二、將數據從父組件傳遞到子組件,若有多個數據要傳遞,如1000個,可一次性傳遞,參數傳遞過程時,注意父組件和子組件中各自屬性的名稱,與前面代碼相比,下列代碼對應屬性名稱有所改變(父組件中的 state.xxx 在子組件中獲取的形式為 props.xxx)
父組件代碼
1 var React = require('react');
2 var ReactDOM = require('react-dom'); 3 import BodyChild from './components/indexchild'; 4 5 class Index extends React.Component { 6 7 constructor() { 8 //調用基類的所有的初始化方法 9 super(); 10 11 // 設置當前組件的屬性 12 this.state = { 13 username: "Guang", 14 age: 20 15 }; 16 }; 17 18 render() { 19 return ( 20 <div> 21 <h3>子組件</h3> 22 23 {/* 顯示當前組件的屬性作為對照 */} 24 <p>age_parent: {this.state.age}</p> 25 <p>username: {this.state.username}</p> 26 27 {/* 一次性傳遞當期組件的所有 state 中的屬性傳給子組件 同理:傳遞 props 可使用 {...this.props} */} 28 <BodyChild{...this.state}/> 29 30 </div> 31 ); 32 } 33 } 34 35 ReactDOM.render( 36 <Index/>, document.getElementById('example'));
子組件代碼
1 import React from 'react';
2
3 export default class BodyChild extends React.Component{ 4 5 constructor(props){ 6 // React組件的構造函數將會在裝配之前被調用。當為一個React.Component子類定義構造函數時, 7 // 你應該在任何其他的表達式之前調用super(props)。否則,this.props在構造函數中將是未定義,並可能引發異常 8 super(props); 9 10 // 父組件傳遞過來的屬性存儲在 props.username 中,將其賦值給當前組件的 state.username_child 11 this.state={username_child:props.username} 12 } 13 14 render(){ 15 return( 16 <div> 17 <h3>子組件</h3> 18 19 {/* 父組件傳遞過來的屬性存儲在 props.age 中,獲取並顯示屬性的值 */} 20 <p>age_child(一次性傳遞,通過 props 獲得): {this.props.age}</p> 21 22 {/* 獲取並顯示 state.username_child,該屬性的值是從父組件中獲取的 */} 23 <p>username_child(一次性傳遞,通過 props 賦值給 state 獲得): {this.state.username_child}</p> 24 25 </div> 26 ) 27 } 28 }
運行結果:

說完了數據從父組件到子組件的傳遞,接下來是數據從子組件到父組件,與前者相比,后者的相對復雜,其傳遞方式一般為:在子組件中通過調用父組件傳遞過來的事件函數進行數據的傳遞 ,即
1、首先在父組件中定義一個函數(用於數據的傳遞,里面處理獲取的各項數據)
2、將函數通過 “數據從父組件傳遞到子組件” 的方式將函數傳遞到子組件
3、在子組件中通過事件綁定或着直接調用的方式執行函數(執行時可以傳入數據、事件等),最終實現數據的傳遞
數據從子組件到父組件
例1:直接傳遞數據
父組件代碼:
1 var React = require('react');
2 var ReactDOM = require('react-dom'); 3 import BodyChild from './components/indexchild'; 4 class Index extends React.Component { 5 constructor() { 6 super(); //調用基類的所有的初始化方法 7 this.state = { 8 username: "Tom", 9 age: 20, 10 child_data:"子組件的輸入在此顯示", 11 }; //初始化賦值 12 }; 13 14 parentGetData(child_username,child_age){ 15 this.setState({child_username:child_username,child_age:child_age}); 16 // console.log(child_username,child_age); 17 } 18 19 render() { 20 return ( 21 <div> 22 <h3>子組件的信息 用戶名為:Guang Zai 年齡為:18 開始時為空,點擊按鈕可獲取</h3> 23 <p>子組件用戶名:{this.state.child_username}</p> 24 <p>子組件年齡:{this.state.child_age}</p> 25 <BodyChild childGetData={(n1,n2)=>this.parentGetData(n1,n2)}/> 26 </div> 27 ); 28 } 29 } 30 ReactDOM.render( 31 <Index/>, document.getElementById('example'));
子組件代碼:
1 import React from 'react';
2
3 export default class BodyChild extends React.Component{ 4 5 constructor(props){ 6 // React組件的構造函數將會在裝配之前被調用。當為一個React.Component子類定義構造函數時, 7 // 你應該在任何其他的表達式之前調用super(props)。否則,this.props在構造函數中將是未定義,並可能引發異常 8 super(props); 9 this.state={ 10 username:"Guang Zai", 11 age:18 12 } 13 } 14 render(){ 15 return( 16 <div> 17 <p>子組件按鈕:<input type="button" value="點擊獲取子組件信息" onClick={()=>this.props.childGetData(this.state.username,this.state.age)}></input></p> 18 </div> 19 ) 20 } 21 }
運行結果:

例2:通過事件傳遞數據
父組件代碼:
1 var React = require('react');
2 var ReactDOM = require('react-dom'); 3 import BodyChild from './components/indexchild'; 4 class Index extends React.Component { 5 constructor() { 6 super(); //調用基類的所有的初始化方法 7 this.state={child_data:"此處實時顯示子組件輸入的信息"} 8 9 // 初始化時 函數 this 使用 bind 綁定當前類 10 this.parentPageInputBind=this.parentPageInputBind.bind(this); 11 }; 12 13 parentPageInputBind(e){ 14 this.setState({child_data:e.target.value}); 15 }; 16 17 render() { 18 return ( 19 <div> 20 <h3>子組件實時輸入的信息</h3> 21 <p>實時輸入的信息:{this.state.child_data}</p> 22 <BodyChild childPageInputBind={this.parentPageInputBind}/> 23 </div> 24 ); 25 } 26 } 27 ReactDOM.render( 28 <Index/>, document.getElementById('example'));
子組件代碼:
1 import React from 'react';
2
3 export default class BodyChild extends React.Component{ 4 render(){ 5 return( 6 <div> 7 <p>子組件輸入:<input type="text" onChange={this.props.childPageInputBind}></input></p> 8 </div> 9 ) 10 } 11 }
運行結果:

多個組件共享狀態數據
綜合上述參數的雙向傳遞,通過將多個子組件輸入的數據傳遞到同一個父組件,然后將該父組件中處理好的數據傳遞回給需要的子組件,實現數據間的共享
1 import React from 'react'; 2 3 class LettersInput extends React.Component{ 4 constructor(props){ 5 super(props); 6 } 7 handleChange(e){ 8 this.props.onLettersChange(e); 9 } 10 render(){ 11 const letters=this.props.letters; 12 return( 13 <div> 14 <input value={letters} onChange={(e)=>this.handleChange(e)}></input> 15 </div> 16 ) 17 } 18 } 19 20 class AppComponent extends React.Component { 21 constructor(props){ 22 super(props); 23 this.state={letters:''}; 24 this.handleChange=this.handleChange.bind(this); 25 } 26 27 handleChange(e){ 28 const letters=e.target.value; 29 const last=letters.substr(letters.length-1,1); 30 if(/[^a-z]/i.test(last)){ 31 return ''; 32 } 33 this.setState({letters:letters}); 34 } 35 36 render(){ 37 const letters=this.state.letters; 38 return( 39 <div> 40 <span>lower case letter:</span><LettersInput letters={letters.toLowerCase()} onLettersChange={this.handleChange}/> 41 <span>upper case letter:</span><LettersInput letters={letters.toUpperCase()} onLettersChange={this.handleChange}/> 42 </div> 43 ) 44 } 45 46 } 47 48 AppComponent.defaultProps = { 49 }; 50 51 export default AppComponent;
運行結果:

