react中(父子/祖先/路由)數據和事件的通信方法總結

好久沒更博了啊,0.0,最近手頭的一個前端控制檯項目,我是用阿里開源的ant框架搭建的,用着還是蠻順手了,在使用過程中,碰到一些數據通信的問題,有些和vue相同,有些不一樣的地方還是踩了些坑的,特地整理了下。

1.子組件調用父級的數據和方法

父級組件代碼如下,把數據和方法通過props向下傳遞,在子組件中調用this.props.text即可獲得父級數據,調用this.props.checkboxCallback()即可調用父級方法

render() {
	const text = this.state.text;
	const checked = this.state.checked;
	return (
		<Row>
			<Col span={24}>
				<ChildComponent 
					ref="child1"
					text={text} 
					checked={checked} 
					inputCallback={this.inputCallback} 
					checkboxCallback={this.checkboxCallback}
				>
				</ChildComponent>
				<button onClick={() => this.log('lemon')}>console</button>
				<button onClick={() => this.changeParentPars()}>改變父層級的值</button>
			</Col>
		</Row>
	)
}

用props這種方法調用的時候,如果傳遞的props是同一個引用對象,那麼只改變父級的state,傳遞給子集的props也會隨之改變,但如果是獨立引用對象,就需要在子集用componentWillReceiveProps監聽屬性值的變化,並隨之setState。

componentWillReceiveProps = (nextProps) =>{
    console.log(nextProps)
    this.setState(nextProps);
};

2.父級調用子組件的數據和方法

和上面的例子一樣,給組件childComponent加上一個ref屬性,相當於dom id,父級組件中調用this.refs.child1.state即可獲取子組件中的數據,調用this.refs.child1.innerMethod(pars)即調用子組件的方法

3.路由

在react中,一切都是組件,路由的話其實就是一個子組件,但要注意的是,用browserHistory.push(path);觸發路由的時候,如果立即調用this.refs.childPage去獲取子組件的話,獲取到的是路由變化前的,這裏需要等路由加載完成後再調用,我翻了半天router的api也沒找到路由完成後的回調,只能用setTimeout 1ms後,再調用就ok了。

class View extends Component {

	componentDidMount = () => {
	};

	tabChange = (key) => {
	    // console.log(key);
	    let mySelf = this;
	    let uid = mySelf.state.uidFromUrl;
	    let uidFormat = (uid)?'?uid=' + uid:'';
	    let path = '/operation/personal/' + key + uidFormat;
	    // console.log(path)
		browserHistory.push(path);
		//等1ms路由切換完成後,再觸發子頁面的查詢
		setTimeout(function(){
	        mySelf.triggerChildPageQuery();
	    },1);
	};

	triggerChildPageQuery = () => {
	    let mySelf = this;
	    let uid = mySelf.state.currentOption.key;
		mySelf.refs.childPage.setUidFromParent(uid);
		mySelf.hideLoading();
	};

	render() {
		return (
			<Spin tip="Loading..." spinning={loading} size="large">
				{mySelf.props.children && React.cloneElement(mySelf.props.children, {
					hideLoading: mySelf.hideLoading,
					ref: "childPage",
				})}
			</Spin>
		)
	}
    
}

4.祖先傳參

業務場景是這樣的,路由子頁面需要設置祖先頁面的currentMenu,以達到切換tab的同時,高亮當前菜單的效果,由於路由的層級可能是很多層,如果逐層地父子通信,會很複雜,我這邊是用prop-types實現的。


具體實現,首先需要安裝一個名叫'prop-types'的庫,在父級菜單使用getChildText方法,來給子context對象的屬性賦值,子集中用mySelf.context來直接調用祖先的函數即可。

父級:

import PropTypes from 'prop-types';

class FrameWork extends Component {

    componentDidMount = () =>{
    };

    getChildContext(){
        return {
            updateCrumbs: this.updateCrumbs(),
            crumbPars: this.state.crumbPars,
            updateMenu:this.onChangeMenu(),
        }
    };

    onChangeMenu = (key) => {
        // let mySelf = this;
        return (key) => {
            this.setState({currentMenu:key})
        }
    };
    
    render() {
    	blabla....
    }
}

//定義了頂層組件所擁有的子類context對象——該頂層組件所擁有的的子類context對象爲color,且必須爲字符串。
FrameWork.childContextTypes = {
    crumbPars: PropTypes.any,
    updateCrumbs: PropTypes.any,
    updateMenu: PropTypes.any,
};

export default FrameWork;

子:

class View extends Component {

	componentDidMount = () => {
        this.initTab();
	};

	initTab = () => {
	    let mySelf = this;
		mySelf.context.updateMenu("operationEnterprise");
	};
}

View.contextTypes = {
	updateMenu: PropTypes.any
};

export default View;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章