react 組件之間傳值的方案有不少,下面是我我的經驗的總結
github 地址javascript
通常在表單頁面中用到組件時候會用到props 傳遞值,須要注意下,最好頁面的狀態控制都在該頁面的頂級節點的state 的,不要嘗試獲取或控制子節點的state,因此組件內部state是父級節點不關心的java
import React,{Component} from 'react'; import PropTypes from 'prop-types' class ChildNode extends Component{ static PropTypes={ value:PropTypes.string.isRequired, onChange:PropTypes.func.isRequired } render(){ const {value,onChange} = this.props; return ( <div> <span>這裏是子節點值:{value}</span><br/> <input type="text" value={value} onChange={(e)=>{ console.log('開始更改值') onChange(e.target.value) }}/> </div> ) } } class Parent extends Component{ state={ childValue:'this is the value of the child node' } onChildValueChange=(val)=>{//注意這裏用ES6 的array function 來綁定當前的this this.setState({childValue:val}) } render(){ const {childValue} = this.state; return ( <div> <span>這裏是父節點</span> <div> <span>父節點控制子節點的內容</span> <button onClick={()=>{ let childValue = this.state.childValue||"" this.setState({ childValue:childValue+'我最帥!' }) }}>內容直接加上我最帥</button> </div> <br/> <br/> <ChildNode value={childValue} onChange={this.onChildValueChange}/> </div> ) } } export default Parent;
這裏使用redux-react 來鏈接 react 和 redux。node
獲取值:經過redux-react connect()react
傳遞值:經過dispatch 具體的actiongit
能夠藉助文件夾名稱的約定和第三方組件來彌補上面的缺點github
經過connect 傳遞過來的props 值不能修改哦。只讀的!redux
import React,{Component} from 'react' import {createStore,combineReducers} from 'redux' import { Provider,connect } from 'react-redux' /** * reducer 用來描述state 是怎樣改變的 * @param state * @param action * @returns {number} */ function reducerOne(state=0,action){ switch (action.type) { case 'reducerOne/INCREMENT': return state + 1 case 'reducerOne/DECREMENT': return state - 1 default: return state } } const store = createStore(combineReducers({reducerOne})) class ReduxNodeOne extends Component{ render(){ return ( <div> <h6>節點一</h6> <button onClick={()=>{ this.props.increment() }}>加1</button> <button onClick={()=>{ this.props.decrement() }}>減1</button> </div> ) } } class ReduxNodeTwo extends Component { render(){ return ( <div> <h6>節點二</h6> <span>Counter:{this.props.counter}</span> </div> ) } } const ConnectedReduxNodeTwo = connect(({reducerOne})=>{ return { counter:reducerOne } })(ReduxNodeTwo) const ConnectedReduxNodeOne= connect(null,{ increment:function(){ return { type:'reducerOne/INCREMENT' } }, decrement:function(){ return { type:'reducerOne/DECREMENT' } } })(ReduxNodeOne) export default function(){ return ( <Provider store={store}> <div> <h1>Redux Simple Demo</h1> <ConnectedReduxNodeOne /> <ConnectedReduxNodeTwo/> </div> </Provider> ) };
純react 頁面的時候,若是數據的傳遞要經過多層react 對象的時候,你能夠考慮context 傳遞值哦。框架
獲取值:子組件內定義static contextTypes={ name:PropTypes.string.isRequired, }
在經過this.context 去獲取ide
傳遞值:父組件定義static childContextTypes={ name:PropTypes.string }
和getChildContext(){ return { name:'爺爺' } }
ui
Demo 以下:
import React,{Component} from 'react' import PropTypes from 'prop-types' class ContextParent extends Component{ static childContextTypes={ name:PropTypes.string } render(){ return ( <div> Node Parent {this.props.children} </div> ) } getChildContext(){ return { name:'爺爺' } } } class Context extends Component{ render(){ return <div> Current Node {this.props.children} </div> } } class ContextChild extends Component{ static contextTypes={ name:PropTypes.string.isRequired, } render(){ return ( <div> Node Children <span>Parent:{this.context.name}</span> </div> ) } } export default function(){ return ( <ContextParent> <Context> <ContextChild/> </Context> </ContextParent> ) }
經過 eventemitter3 library 實現,也能夠用其餘的event 庫
該傳值方案通常做爲react state 存儲數據時候須要聯動觸發的業務邏輯以及專業填上線前出現的業務邏輯的代碼坑。
獲取值:經過在constructor 裏面監聽event 事件,再setState到內部state
傳遞值: 觸發 emit 事件
import React,{Component} from 'react' import EventEmitter from 'eventemitter3'; const EVENT = new EventEmitter(); class NodeOne extends Component{ constructor(props){ super(props) this.state={ counter:0 }; EVENT.on('NodeOne:increment',(num)=>{ this.setState({ counter:this.state.counter+num }) }) } render(){ return ( <div> <h4>Node One 當前counter:{this.state.counter}</h4> <button onClick={()=>{ EVENT.emit('NodeTwo:increment',20) }}>Node Two 加 20</button> </div> ) } } class NodeTwo extends Component{ constructor(props){ super(props) this.state={ counter:0 }; EVENT.on('NodeTwo:increment',(num)=>{ this.setState({ counter:this.state.counter+num }) }) } render(){ return ( <div> <h4>Node Two當前counter:{this.state.counter}</h4> <button onClick={()=>{ EVENT.emit('NodeOne:increment',5) }}>Node One 加 5</button> </div> ) } } export default function(){ return ( <div> <NodeOne/> <NodeTwo/> </div> ) }