React學習:元件生命週期、元件間資料傳遞
阿新 • • 發佈:2019-02-06
注:本篇文章僅供個人日後複習,所以沒什麼乾貨,只起類似“備忘錄”的作用。
最近,在看《深入淺出React和Redux》,目前到第二章了,這是本章程式碼:
(1)counter.js
import React, { Component } from 'react'; import PropTypes from 'prop-types'; const buttonStyle = { margin: '10px' }; class Counter extends Component { constructor(props) { console.log('enter constructor: ' + props.caption); super(props);// 為了獲得父元件傳進來的prop // bind()方法會建立一個新函式,稱為繫結函式, // 當呼叫這個繫結函式時,繫結函式會以建立它時傳入 bind()方法的第一個引數作為 this, // 傳入 bind() 方法的第二個以及以後的引數加上繫結函式執行時本身的引數 // 按照順序作為原函式的引數來呼叫原函式 this.onClickIncrementButton = this.onClickIncrementButton.bind(this); this.onClickDecrementButton = this.onClickDecrementButton.bind(this); this.state = { count: props.initValue||0 } } /* // 在ES6中不會用到 getInitialState() { console.log('enter getInitialState'); } getDefaultProps() { console.log('enter getDefaultProps'); } */ componentWillReceiveProps(nextProps) { console.log('enter componentWillReceiveProps ' + this.props.caption) } componentWillMount() { console.log('enter componentWillMount ' + this.props.caption); } componentDidMount() { console.log('enter componentDidMount ' + this.props.caption); } onClickIncrementButton() { //this.setState({count: this.state.count + 1}); this.updateCount(true); } onClickDecrementButton() { //this.setState({count: this.state.count - 1}); this.updateCount(false); } updateCount(isIncrement){ const previousValue=this.state.count; const newValue=isIncrement?previousValue+1:previousValue-1; this.setState({count:newValue}); this.props.onUpdate(newValue,previousValue); } shouldComponentUpdate(nextProps, nextState) { return (nextProps.caption !== this.props.caption) || (nextState.count !== this.state.count); } render() { console.log('enter render ' + this.props.caption); const {caption} = this.props; return ( <div> <button style={buttonStyle} onClick={this.onClickIncrementButton}>+</button> <button style={buttonStyle} onClick={this.onClickDecrementButton}>-</button> <span>{caption} count: {this.state.count}</span> </div> ); } } Counter.propTypes = { caption: PropTypes.string.isRequired, initValue: PropTypes.number, onUpdate: PropTypes.func }; Counter.defaultProps = { initValue: 0, onUpdate:f => f }; export default Counter;
(2)controlPanel.js
import React, { Component } from 'react'; import Counter from './Counter.js'; // 這是元件離左右兩邊的margin const style = { margin: '20px' }; class ControlPanel extends Component { constructor(props){ super(props); this.onCounterUpdate=this.onCounterUpdate.bind(this); this.initValues=[0,10,20]; const initSum=this.initValues.reduce((a,b)=>a+b,0); this.state={ sum:initSum }; } render() { console.log('enter ControlPanel render'); return ( <div style={style}> <Counter onUpdate={this.onCounterUpdate} caption="First"/> <Counter onUpdate={this.onCounterUpdate} caption="Second" initValue={this.initValues[1]} /> <Counter onUpdate={this.onCounterUpdate} caption="Third" initValue={this.initValues[2]} /> <button onClick={ () => this.forceUpdate() }> Click me to re-render! </button> <hr/> <div>Total Count:{this.state.sum}</div> </div> ); } onCounterUpdate(newValue,previousValue){ const valueChange=newValue-previousValue; this.setState({sum:this.state.sum+valueChange}); } } // 輸出這個模組 export default ControlPanel;
關於生命週期的問題,書中已經說得很好了,不再贅述。
程式碼中不同元件之間傳資料的方法要掌握。例如這裡是在counter中建立了一個空函式onUpdate,每次點選都會呼叫它,傳入引數newValue和previousValue,然後在元件controlPanel的每個counter例項中,將onCounterUpdate繫結到這個prop上(也就相當於將引數傳給了onCounterUpdate)。