組件之間的傳值

組件之間的傳值,包括父子組件傳值,?兄弟組件之間的傳值,其中父子組件包括父組件向子組件傳值和子組件向父組件傳值,現(xiàn)在一一來介紹一下.

一.父組件向子組件傳值

? ? 父組件通過state向子組件傳值,?

// 父組件

constructor(props){

????super(props);

????this.state = { name : 'yuxi' }}

render(){ return 我是子組件 }

// 子組件

constructor(props){

super(props)

}

render(){

return <div>{this.props.name}<div>

}

二.子組件向父組件傳值

? ? 有三種方式實(shí)現(xiàn)子組件向父組件傳值.?

(一)父組件通過state傳值給子組件,子組件通過props獲取父組件的傳遞值

? ? //(一)傳值,即在父組件中聲明好自己的state,然后傳值,如下//1.初始值constructor() {

? ? super();

? ? this.state = {

? ? ? stateValue:true? ? }

? }//2.如有改變?cè)O(shè)定值this.setState({

? ? stateValue: false})//3.在父組件中傳值

? ? const huoquValue = this.props.stateValue;

? ? if ( !this.props.stateValue ) {

? ? ? ? console.log('stateValue', this,.props.stateValue)

? ? }

}

值得注意一點(diǎn)的是,setState 是一個(gè)異步方法,需要render值行的時(shí)候才會(huì)觸發(fā)??梢詤⒖疾┛汀?a target="_blank" rel="nofollow">?React的setState立即執(zhí)行方案】。

(二)父組件將方法傳給子組件,子組件通過props來獲取。

//父組件文件中:

????classTestHtmlextendsReact.Component{

????//1.方法的聲明

????propsFunction() {

? ? ? ? console.log('聲明在父組件的方法')

? ? }

? ? render() {

? ? ? ? return (

? ? ? ? ? ? //2.傳遞? ? ? ? ? ?

? ? ? ? )

? ? }

}functionmapStateToProps(state, ownProps){? ? return {

? ? }

}functionmapDispatchToProps(dispatch){? ? return {

? ? ? ? ...bindActionCreators(action, dispatch)

? ? }

}

export default connect(mapStateToProps, mapDispatchToProps)(TestHtml)

//子組件中獲取

<Button onClick={this.props.propsFunction} />

說明:寫這一段的時(shí)候,突發(fā)奇想,竟然就把react-redux的頁面結(jié)構(gòu)的寫出來了。好吧,等下寫完這篇,如果有必要就具體寫一下這個(gè)頁面的結(jié)構(gòu)類型吧。

(三)在父組件中調(diào)用子組件中的方法,通過ref和refs實(shí)現(xiàn)。

//這里就簡要說明一下

//思路是給子組件一個(gè)ref,然后父組件通過refs獲取

componentWillReceiveProps(nextProps) {

? ? this.refs.jiedian.子組件的方法名()

? ? //舉個(gè)例子

? ? // this.refs.getSwordButton.setFieldsValue({

? ? //? xmlUrl: nextProps.sysCode==null ? nextProps.accountInfo.xmlUrl : nextProps.sysCode? ? // })

}

(四)特殊情況?

當(dāng)你發(fā)現(xiàn)這些方法都不起作用的時(shí)候,或者說,因?yàn)槟承┫拗贫荒苡玫臅r(shí)候,你就換一下思路了。?

其實(shí)我們還可以通過action–reduce的方式在他們的外部且是公共的action-reduce中搞定。?

其中涉及到方法我們就直接新建一個(gè)方法,在action中聲明,在reduce中實(shí)現(xiàn)。如果只是某個(gè)值,用不到函數(shù)的,我們可以直接在reduce里面設(shè)定,且賦值,最后通過mapStateToProps獲取。?

關(guān)于mapStateToProps,可以直接參考【React依賴注入說明(mapStateToProps/mapDispatchToProps)

總結(jié)?

1.父組件通過state向子組件傳值,子組件通過props獲取父組件所傳的值。?

2.子組件通過prop獲取父組件中定義的函數(shù)方法,但是需要在父組件調(diào)用子組件的標(biāo)簽中寫明。?

3.父組件通過refs調(diào)用子組件中聲明的方法,但是需要給子組件添加一個(gè)ref節(jié)點(diǎn)?

4.組件之間的交流也不一定要沉在這些直接性的關(guān)聯(lián)的東西,我們的思維還可以提神一個(gè)高度,可以在action-reduce中搞定。?

三.?兄弟組件之間傳值


兄弟組件的意思就是指沒有任何嵌套關(guān)系的組件之間傳值.?這種需求也是非常常見的,

如果組件之間沒有任何關(guān)系,組件嵌套層次比較深(個(gè)人認(rèn)為 2 層以上已經(jīng)算深了),或者你為了一些組件能夠訂閱、寫入一些信號(hào),不想讓組件之間插入一個(gè)組件,讓兩個(gè)組件處于獨(dú)立的關(guān)系。對(duì)于事件系統(tǒng),這里有 2 個(gè)基本操作步驟:訂閱(subscribe)/監(jiān)聽(listen)一個(gè)事件通知,并發(fā)送(send)/觸發(fā)(trigger)/發(fā)布(publish)/發(fā)送(dispatch)一個(gè)事件通知那些想要的組件。

下面講介紹 3 種模式來處理事件,你能點(diǎn)擊這里來比較一下它們。

簡單總結(jié)一下:

(1) Event Emitter/Target/Dispatcher

特點(diǎn):需要一個(gè)指定的訂閱源

// to subscribe

otherObject.addEventListener(‘click’,function(){ alert(‘click!’); });

// to dispatch

this.dispatchEvent(‘click’);

(2) Publish / Subscribe

特點(diǎn):觸發(fā)事件的時(shí)候,你不需要指定一個(gè)特定的源,因?yàn)樗鞘褂靡粋€(gè)全局對(duì)象來處理事件(其實(shí)就是一個(gè)全局

廣播的方式來處理事件)

// to subscribe

globalBroadcaster.subscribe(‘click’,function(){ alert(‘click!’); });

// to dispatch

globalBroadcaster.publish(‘click’);

(3) Signals

特點(diǎn):與Event Emitter/Target/Dispatcher相似,但是你不要使用隨機(jī)的字符串作為事件觸發(fā)的引用。觸發(fā)事件的每一個(gè)對(duì)象都需要一個(gè)確切的名字(就是類似硬編碼類的去寫事件名字),并且在觸發(fā)的時(shí)候,也必須要指定確切的事件。(看例子吧,很好理解)

// to subscribe

otherObject.clicked.add(function(){ alert(‘click’); });

// to dispatch

this.clicked.dispatch();

如果你只想簡單的使用一下,并不需要其他操作,可以用簡單的方式來實(shí)現(xiàn):

// 簡單實(shí)現(xiàn)了一下 subscribe 和 dispatch

varEventEmitter = {

? ? _events: {},

dispatch: function (event,data) {

if(!this._events[event]) {// 沒有監(jiān)聽事件

return;

? ? ? ? }

for(vari =0; i

this._events[event][i](data);

? ? ? ? }

? ? },

? ? subscribe: function (event, callback) {

// 創(chuàng)建一個(gè)新事件數(shù)組

if(!this._events[event]) {

this._events[event] = [];

? ? ? }

this._events[event].push(callback);

? ? }

};

otherObject.subscribe('namechanged', function(data) { alert(data.name); });

this.dispatch('namechanged', { name:'John'});

如果你想使用 Publish/Subscribe 模型,可以使用:PubSubJS

React 團(tuán)隊(duì)使用的是:js-signals它基于 Signals 模式,用起來相當(dāng)不錯(cuò)。

Events in React

使用 React 事件的時(shí)候,必須關(guān)注下面兩個(gè)方法:

componentDidMount

componentWillUnmount

在處理事件的時(shí)候,需要注意:

在 componentDidMount 事件中,如果組件掛載(mounted)完成,再訂閱事件;當(dāng)組件卸載(unmounted)的時(shí)候,在 componentWillUnmount 事件中取消事件的訂閱。

(如果不是很清楚可以查閱 React 對(duì)生命周期介紹的文檔,里面也有描述。原文中介紹的是 componentWillMount 個(gè)人認(rèn)為應(yīng)該是掛載完成后訂閱事件,比如Animation這個(gè)就必須掛載,并且不能動(dòng)態(tài)的添加,謹(jǐn)慎點(diǎn)更好)

因?yàn)榻M件的渲染和銷毀是由 React 來控制的,我們不知道怎么引用他們,所以EventEmitter 模式在處理組件的時(shí)候用處不大。

pub/sub 模式可以使用,你不需要知道引用。

下面來一個(gè)例子:實(shí)現(xiàn)有多個(gè) product 組件,點(diǎn)擊他們的時(shí)候,展示 product 的名字。

(我在例子中引入了之前推薦的 PubSubJS 庫,如果你覺得引入代價(jià)太大,也可以手寫一個(gè)簡版,還是比較容易的,很好用哈,大家也可以體驗(yàn),但是我還是不推薦全局廣播的方式)

// 定義一個(gè)容器

varProductList = React.createClass({

render:function(){

return(

? ? <div>

? ? ? ? ? ? <ProductSelection />

? ? ? ? ? ? <Product name="product 1" />

? ? ? ? ? ? <Product name="product 2"/>

? ? ? ? ? ? <Product name="product 3" />

????</div>

? ? ? );

? ? }

});

// 用于展示點(diǎn)擊的產(chǎn)品信息容器

varProductSelection = React.createClass({

getInitialState:function(){

return{

selection:'none'

? ? };

? },

componentDidMount:function(){

this.pubsub_token = PubSub.subscribe('products',function(topic, product){

? ? ? this.setState({

? ? ? ? selection: product

? ? ? });

? ? }.bind(this));

? },

componentWillUnmount:function(){

? ? PubSub.unsubscribe(this.pubsub_token);

? },

render:function(){

return(


You have selected the product : {this.state.selection}

? ? );

? }

});

varProduct = React.createClass({

onclick:function(){

PubSub.publish('products', this.props.name);

? },

render:function(){

return

{this.props.name}

;

? }

});

ES6: yield and js-csp

ES6 中有一種傳遞信息的方式,使用生成函數(shù)(generators)和 yield 關(guān)鍵字。可以看一下https://github.com/ubolonton/js-csp

(這里我寫一個(gè)簡單的 DEMO 介紹一下這種新的傳遞方式,其實(shí)大同小異)

function*list(){

for(vari =0; i

yieldarguments[i];

? ? }

return"done.";

}

varo = list(1,2,3);

varcur = o.next;

while(!cur.done) {

? ? cur = o.next();

console.log(cur);

}

以上例子來自于屈屈的一篇博客:ES6 中的生成器函數(shù)介紹? 屈屈是一個(gè)大牛,大家可以關(guān)注他的博客。

通常來說,你有一個(gè)隊(duì)列,對(duì)象在里面都能找到一個(gè)引用,在定義的時(shí)候鎖住,當(dāng)發(fā)生的時(shí)候,立即打開鎖執(zhí)行。js-csp 是一種解決辦法,也許以后還會(huì)有其他解決辦法。

結(jié)尾

在實(shí)際應(yīng)用中,按照實(shí)際要解決的需求選擇解決辦法。對(duì)于小應(yīng)用程序,你可以使用 props 和回調(diào)的方法進(jìn)行組件之間的數(shù)據(jù)交換。你可以通過 pub/sub 模式,以避免污染你的組件。在這里,我們不是在談?wù)摂?shù)據(jù),只是組件。對(duì)于數(shù)據(jù)的請(qǐng)求、數(shù)據(jù)的變化等場景,可以使用 Facebook 的 Flux、Relay、GraphQL 來處理,都非常的好用。

文中的每一個(gè)例子我都驗(yàn)證過了,主要使用最原始的引入文件方式,創(chuàng)建服務(wù)使用的 http-server 包,大家也可以嘗試自己來一次。



參考文檔:? ? 1.?https://blog.csdn.net/limm33/article/details/50942863

2.http://www.itdecent.cn/p/8b845f05cf4b

3.https://blog.csdn.net/genius_yym/article/details/73057248

4.?https://segmentfault.com/q/1010000007295553?_ea=1300560

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 三種傳值情況的實(shí)現(xiàn)步驟描述 : VUE是單向數(shù)據(jù)流。父組件內(nèi)的數(shù)據(jù)的作用域就是父組件,子組件或者兄弟組件都無法直接...
    谷子多閱讀 2,295評(píng)論 0 2
  • 重點(diǎn)?。?!當(dāng)初學(xué)這個(gè)時(shí)候,糾結(jié)了好一會(huì)兒。先來看看組件關(guān)系。 可以把一個(gè)網(wǎng)頁拆分成很多部分,如圖所示,可以理解為一...
    八寶君閱讀 3,024評(píng)論 9 7
  • 1.新建home.vue 和header.vue 組件 2.父組件home 屬性傳值 3.子組件接收父子的傳值 總...
    undefind33閱讀 333評(píng)論 0 0
  • 窩在家里哭了幾天,今天他過來我家,告訴我做出了選擇,結(jié)束這段感情。雖然我早已心中有數(shù),但是這一刻來臨時(shí),我崩潰大哭...
    chen以潔閱讀 338評(píng)論 2 2
  • 今天是霍春燕大婚的日子,婚禮上她哭得梨花帶雨,她最感謝的有幾個(gè)人,一個(gè)是自己的男朋友,另外就是自己的父母,確切來說...
    BIGPeople閱讀 416評(píng)論 0 0

友情鏈接更多精彩內(nèi)容