React生命周期详细图解

297 阅读11分钟
前言

鉴于网上很多有关React生命周期的图解似乎都都不详细,于是近期整理了一下React的生命周期,跟大家分享一下,建议关注收藏,可以时不时回顾一下,如有不对的地方望大家指出,一起学习!

图解

以下是代码和运行过程

父组件 DetailScreen.js
//楼盘详情 created by 轮子弟
import React, {Component} from 'react';

import {
  View,
  Text,
  Button,
  StyleSheet,
  ScrollView,
  ImageBackground,
  Image,
  TouchableOpacity,
  Dimensions,
  RefreshControl,
  DeviceEventEmitter,
} from 'react-native';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import * as DetailsActions from '../../../reducers/detailsReducers/DetailsAction';
import store from '../../../configureStore';

import * as api from '../../../networking/Api';
import ConcactInformation from '../../../component/detail/ConcactInformation'; //中介联系方式浮窗
import StatisticsAudience from '../../../component/detail/StatisticsAudience'; //围观人数
import HouseType from '../../../component/detail/HouseType'; //户型
import ItemTitle from '../../../component/detail/ItemTitle'; //自定义标题
import AgentHouse from '../../../component/detail/AgentHouse'; //经纪人楼盘
import MapComponent from '../../../component/detail/MapComponent'; //地图
import ShowPictures from '../../../component/detail/ShowPictures'; //轮播
import TimeAxis from '../../../component/detail/TimeAxis'; //楼盘动态时间轴

const image = {uri: 'https://reactjs.org/logo-og.png'};
// const image = require('./../../resources/cHomeTab/photo/banner.png')
const opening_time = require('./../../../resources/cHomeTab/icon/opening_time.png');
const decoration = require('./../../../resources/cHomeTab/icon/decoration.png');
const developers = require('./../../../resources/cHomeTab/icon/developers.png');
const property_address = require('./../../../resources/cHomeTab/icon/property_address.png');
const sharePhoto = require('./../../../resources/cHomeTab/icon/sharePhoto.png');
// import Banner from './home/component/Swiper_'

const window = Dimensions.get('window');
const screen = Dimensions.get('screen');

class DetailScreen extends Component {
  constructor(props, context) {
    //Provider是通过context传递给子组件的,子组件通过connect获得数据,实现过程如下,可以看到在没有定义props的情况下,通过context直接取得store中的数据。
    // this.store = props.store || context.store
    console.log('页面控制器~~~~');
    super(...arguments);
    this.state = {
      refreshing: false,
      aa: '窝窝头一块钱四个',
      bb: '嗝',
    };
  }
  componentWillMount() {
    console.log('页面挂载前~~~~');
  }
  componentDidMount() {
    console.log('页面挂载完成~~~~');
    console.log('this.props.banner------', this.props.banner);
    this._onRefresh();

    //  页面加载完成时注册监听,等DeviceEventEmitter.emit('Refresh')触发后,回到本页面时执行,相当于
    this.listener = DeviceEventEmitter.addListener('Refresh', () => {
      console.log('有混蛋来了 pao~~~~');
      this._onRefresh();
    });
    setTimeout(() => {
      console.log('this.props.banner+++++', this.props.banner);
    }, 500);
  }

  componentWillUpdate() {
    console.log('页面准备更新~~~~');
  }

  componentDidUpdate() {
    console.log('页面更新完成~~~~');
  }

  componentWillUnmount() {
    console.log('页面卸载了~~~~');
    this.listener.remove();
  }
  componentWillReceiveProps(nextProps) {
    console.log('this.props:', this.props, 'nextProps:', nextProps);
  }

  // shouldComponentUpdate(newProps, newState) {
  //   console.log('页面更新拦截钩子~~~~');
  //   if (newState.a == 'bb') return false;
  //   return true; //true更新  false阻止更新
  // }
  _onRefresh = () => {
    console.log('this.props.banner', this.props.banner);
    console.log('this.props.refreshing', this.props.refreshing);
    const houseId = '1790';

    // 普通写法(refreshing可以由Store中的中央状态控制,也可以直接setState控制)
    // this.setState({refreshing:true})
    // DetailsActions.asyncGetHousePhotos(houseId)
    //       .then((response) => {
    //         this.setState({refreshing:false})
    //           if (response.type === 'GetHousePhotos') {
    //               console.log('response.banner',response.banner);
    //               this.props.added({type:response.type,banner:response.banner})
    //               console.log('this.props.banner',this.props.banner);
    //               this.props.test({a:'01'});
    //               this.props.test2({a:'02'});
    //               console.log('this.props.testData',this.props.testData);
    //               console.log('this.props.testData2',this.props.testData2);
    //           }
    //       })
    //       .catch((error) => {
    //           return error
    //       })

    // redux-thunk写法(refreshing需要由Store中的中央状态控制)
    this.props.toGetHousePhotos(houseId); //刷新轮播
    setTimeout(() => {
      console.log('更新后this.props.banner', this.props.banner);
      console.log('更新后this.props.refreshing', this.props.refreshing);
    }, 500);
  };

  // 点击更新
  _goToDetails = () => {
    // this.props.navigation.navigate('Map');
    console.log('点击测试更新了~~~~');
    this.setState({
      aa: '嘿嘿',
    });
  };

  render() {
    console.log('父页面挂载中~~~~');
    return (
      <View style={{flex: 1}}>
        <ScrollView
          style={styles.Scroll}
          refreshControl={
            <RefreshControl
              refreshing={this.props.refreshing}
              onRefresh={() => {
                this._onRefresh();
              }}
            />
          }>
          <View style={{backgroundColor: '#f5f5f5'}}>
            {/* 图片展示 */}

            <ShowPictures navigation={this.props.navigation} />
            <View style={styles.houseMsg}>
              <View style={styles.houseName}>
                <Text style={styles.houseTitle}>保利鱼珠港</Text>
                <Text style={styles.status}>即将发售</Text>
              </View>
              <Text style={styles.description}>
                珠江中轴之上,位于广州第二CBD最核心区域
              </Text>
              <View style={styles.label}>
                <Text style={styles.SpecificLabel}>专车带看</Text>
                <Text style={styles.SpecificLabel}>电梯房</Text>
                <Text style={styles.SpecificLabel}>双拼</Text>
                <Text style={styles.SpecificLabel}>国际化社区</Text>
              </View>
              <Text style={styles.price}>36500元/m²</Text>
            </View>

            <View>
              <View>
                <View style={styles.projectInformation}>
                  <View style={styles.informationList}>
                    <Image source={opening_time} style={styles.icon} />
                    <View style={styles.listContent}>
                      <Text style={styles.listText}>开盘时间:</Text>
                      <Text style={styles.listText}>2018年10月</Text>
                    </View>
                  </View>
                  <View style={styles.informationList}>
                    <Image source={decoration} style={styles.icon} />
                    <View style={styles.listContent}>
                      <Text style={styles.listText}>装修情况:</Text>
                      <Text style={styles.listText}>带装修</Text>
                    </View>
                  </View>
                  <View style={styles.informationList}>
                    <Image source={developers} style={styles.icon} />
                    <View style={styles.listContent}>
                      <Text style={styles.listText}>开发商:</Text>
                      <Text style={styles.listText}>保利发展</Text>
                    </View>
                  </View>
                  <View style={styles.informationList}>
                    <Image source={property_address} style={styles.icon} />
                    <View style={styles.listContent}>
                      <Text style={styles.listText}>楼盘地址:</Text>
                      <Text style={styles.listText}>黄埔黄埔大道动856号</Text>
                    </View>
                  </View>
                </View>
              </View>
              <View style={{backgroundColor: '#fff'}}>
                <TouchableOpacity
                  onPress={() => {
                    this.props.navigation.navigate('ProjectInformation');
                  }}
                  activeOpacity={0.5} //触摸时完全不透明,值越小越透明
                  style={styles.morecontainer}>
                  <Text style={styles.more}>更多项目信息</Text>
                </TouchableOpacity>
              </View>
            </View>
            {/* 围观人数 */}
            <StatisticsAudience />
            <View style={styles.projectItem}>
              <ItemTitle title="项目介绍" />
              <Text style={styles.content}>
                保利鱼珠港位于黄埔大道东,雄踞广州自西向东发展的珠江东进中轴,接力珠江新城,成为下一个十年重点发展区。2017年政府铭文指出将重点发展第二商务区,保利鱼珠正处于第二CBD的核心区,占领城市规划发汗利好。
              </Text>
            </View>
            <View style={styles.projectItem}>
              <ItemTitle
                title="热推户型"
                seeMore="查看更多"
                navigation={this.props.navigation}
              />
              {/* 热推户型 */}
              <TouchableOpacity
                onPress={() => {
                  // Alert.alert(
                  //   "抱歉!暂还不能使用地图",
                  // );
                  this._goToDetails();
                }}
                activeOpacity={0.9} //触摸时完全不透明,值越小越透明
              >
                <Text>点击测试子组件更新情况</Text>
              </TouchableOpacity>
              {/* 子组件1 */}
              <HouseType a={this.state.aa'} />
            </View>

            <View style={styles.projectItem}>
              <ItemTitle
                title="楼盘动态"
                count={24}
                seeMore="查看更多"
                navigation={this.props.navigation}
              />
              {/* 子组件2 */}
              <TimeAxis />
            </View>
            <View style={styles.projectItem}>
              <ItemTitle
                title="位置周边"
                seeMore="查看更多"
                navigation={this.props.navigation}
              />
              {/* 子组件3 */}
              <MapComponent navigation={this.props.navigation} />
            </View>
            <View style={styles.projectItem}>
              <ItemTitle title="经纪人其他楼盘" />
              <AgentHouse />
            </View>
          </View>
        </ScrollView>
        {/* 中介联系方式 */}
        <ConcactInformation />
      </View>
    );
  }
}

export default connect(
  (state, ownProps) => {
    // console.log('detailState',state)
    // console.log('ownProps',ownProps)
    return {
      userId: state.loginReducer.userId,
      banner: state.DetailsReducer.banner,
      refreshing: state.DetailsReducer.refreshing,
      testData: state.DetailsReducer.testData,
      testData2: state.DetailsReducer.testData2,
    };
  },
  (dispatch) => ({
    ...bindActionCreators(DetailsActions, dispatch),
    // 异步操作要写成下面这样才方便
    add: (data) => {
      console.log('data', data);
      dispatch(data);
    },
    added: (data) => {
      console.log('data', data);
      dispatch(data);
    },
  }),
)(DetailScreen);

var styles = StyleSheet.create({
  Scroll: {
    backgroundColor: '#ffffff',
  },
  flexLayout: {
    flexDirection: 'row',
  },
  shareIcon: {
    position: 'absolute',
    top: 10,
    right: 30,
    width: 40,
    height: 40,
  },
  sharePhotoIcon: {
    width: 30,
    height: 30,
    borderRadius: 14,
  },
  projectInformation: {
    paddingLeft: 15,
    backgroundColor: '#ffffff',
    paddingBottom: 10,
  },
  informationList: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  listContent: {
    flexDirection: 'row',
  },
  icon: {
    marginRight: 5,
  },
  listText: {
    color: '#222222',
    fontSize: 16,
    lineHeight: 30,
  },
  morecontainer: {
    backgroundColor: '#f5f5f5',
    alignItems: 'center',
    borderRadius: 3,
    overflow: 'hidden',
    marginLeft: 15,
    marginRight: 15,
  },
  more: {
    lineHeight: 45,
    fontSize: 17,
    color: '#495b84',
  },
  houseMsg: {
    paddingLeft: 15,
    paddingRight: 15,
    backgroundColor: '#ffffff',
    paddingTop: 20,
  },
  houseName: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  houseTitle: {
    color: '#222222',
    fontSize: 20,
    lineHeight: 25,
    marginRight: 10,
  },
  status: {
    height: 25,
    lineHeight: 25,
    backgroundColor: '#fae5e4',
    color: '#ec736f',
    borderRadius: 5,
    overflow: 'hidden',
    paddingLeft: 5,
    paddingRight: 5,
    fontSize: 13,
  },
  description: {
    height: 25,
    lineHeight: 25,
    color: '#545454',
  },
  label: {
    flexDirection: 'row',
  },
  SpecificLabel: {
    height: 20,
    lineHeight: 20,
    fontSize: 13,
    color: '#495b84',
    backgroundColor: '#f5f5f5',
    paddingLeft: 5,
    paddingRight: 5,
    borderRadius: 3,
    overflow: 'hidden',
    marginRight: 10,
  },
  price: {
    fontSize: 25,
    color: '#eb5e36',
    lineHeight: 50,
  },
  projectItem: {
    paddingLeft: 15,
    paddingRight: 15,
    backgroundColor: '#ffffff',
    marginTop: 10,
    paddingTop: 20,
    paddingBottom: 20,
  },
  content: {
    color: '#545454',
    fontSize: 16,
    lineHeight: 22,
  },
});

子组件1 HouseType
import React, {Component} from 'react';
import {
  TouchableOpacity,
  Image,
  StyleSheet,
  View,
  Text,
  ScrollView,
} from 'react-native';

const huxing = require('./../../resources/cHomeTab/photo/huxing.png');
import Test from './test';

export default class HouseType extends Component {
  static defaultProps = {};

  constructor(props) {
    console.log('子页面1控制器~~~~');
    super(props);
    this.state = {};
  }
  componentWillMount() {
    console.log('子页面1挂载前~~~~');
  }
  componentDidMount() {
    console.log('子页面1挂载完成~~~~');
  }
  componentWillUpdate() {
    console.log('子页面1准备更新~~~~');
  }

  componentDidUpdate() {
    console.log('子页面1更新完成~~~~');
  }
  componentWillUnmount() {
    console.log('子页面1已销毁~~~~');
  }
  componentWillReceiveProps(value) {
    console.log('子页面1有属性了~~~~', value);
  }
   shouldComponentUpdate(newProps, newState) {
    console.log('子组件1更新拦截钩子shouldComponentUpdate~~~~');
    if (newProps.a == '嘿嘿') return true;
    return false; //true更新  false阻止更新
  }

  render() {
    console.log('子页面1挂载中~~~~');

    return (
      <ScrollView showsHorizontalScrollIndicator={false} horizontal={true}>
        <Test />
        <TouchableOpacity
          onPress={() => {}}
          activeOpacity={0.5} //触摸时完全不透明,值越小越透明
          style={[
            styles.flexLayout,
            {
              justifyContent: 'space-between',
              alignItems: 'center',
              marginRight: 50,
            },
          ]}>
          <Image source={huxing} style={styles.HouseType} />
          <View style={styles.HouseTypeInfo}>
            <View style={styles.flexLayout}>
              <Text style={[styles.HouseTypeText, {marginRight: 10}]}>
                2房1厅1厨1卫
              </Text>
              <Text style={styles.HouseTypeText}>164m²</Text>
              <Text style={styles.HouseTypeText}>{this.props.a}</Text>
            </View>
            <Text style={styles.briefIntroduction}>
              户型精巧布局,南北通透,多向采光,享受多阳光清风
            </Text>
          </View>
        </TouchableOpacity>
        <TouchableOpacity
          onPress={() => {}}
          activeOpacity={0.5} //触摸时完全不透明,值越小越透明
          style={[
            styles.flexLayout,
            {
              justifyContent: 'space-between',
              alignItems: 'center',
              marginRight: 50,
            },
          ]}>
          <Image source={huxing} style={styles.HouseType} />
          <View style={styles.HouseTypeInfo}>
            <View style={styles.flexLayout}>
              <Text style={[styles.HouseTypeText, {marginRight: 10}]}>
                2房1厅1厨1卫
              </Text>
              <Text style={styles.HouseTypeText}>164m²</Text>
            </View>
            <Text style={styles.briefIntroduction}>
              户型精巧布局,南北通透,多向采光,享受多阳光清风
            </Text>
          </View>
        </TouchableOpacity>
        <TouchableOpacity
          onPress={() => {}}
          activeOpacity={0.5} //触摸时完全不透明,值越小越透明
          style={[
            styles.flexLayout,
            {
              justifyContent: 'space-between',
              alignItems: 'center',
              marginRight: 50,
            },
          ]}>
          <Image source={huxing} style={styles.HouseType} />
          <View style={styles.HouseTypeInfo}>
            <View style={styles.flexLayout}>
              <Text style={[styles.HouseTypeText, {marginRight: 10}]}>
                2房1厅1厨1卫
              </Text>
              <Text style={styles.HouseTypeText}>164m²</Text>
            </View>
            <Text style={styles.briefIntroduction}>
              户型精巧布局,南北通透,多向采光,享受多阳光清风
            </Text>
          </View>
        </TouchableOpacity>
      </ScrollView>
    );
  }
}

const styles = StyleSheet.create({
  flexLayout: {
    flexDirection: 'row',
  },
  HouseType: {
    width: 80,
    height: 70,
  },
  HouseTypeInfo: {
    width: 285,
    paddingLeft: 20,
  },
  HouseTypeText: {
    fontSize: 16,
    lineHeight: 30,
  },
  briefIntroduction: {
    color: '#545454',
    fontSize: 17,
    lineHeight: 25,
  },
});


子组件2 TimeAxis
import React, {Component} from 'react';
import {StyleSheet, View, Text} from 'react-native';
import {connect} from 'react-redux';
import * as api from '../../networking/Api';

class TimeAxis extends Component {
  static defaultProps = {};

  constructor(props) {
    console.log('子页面2控制器~~~~');

    super(props);
    this.state = {
      invoice: [
        {
          id: 1,
          ctime: '2020年01月30日',
          content: '星河丹堤新春购房优惠5重豪礼,购房最高直减72万',
          contentDetails:
            '星河丹堤主力在售D区澜山组团130-139m四五房半山观海揽湖洋房以及219- 235m联排...',
        },
        {
          id: 2,
          ctime: '2020年01月01日',
          content: '星河丹堤唯一半山臻品南向小户型49-77m盛大发售',
          contentDetails:
            '星河丹堤2020年1月1日加推南沙唯一半山臻品小洋房,类公寓设计,2梯9户13层高, 首二...',
        },
        {
          id: 3,
          ctime: '2019年10月01日',
          content: '南沙星河丹堤压轴洋房新品D3栋小高层国庆发售',
          contentDetails:
            '星河丹堤压轴洋房新品--澜山组团D区洋房  首页范区于10月1日全球盛放,同步认购。推售产...',
        },
        {
          id: 3,
          ctime: '2019年10月01日',
          content: '南沙星河丹堤压轴洋房新品D3栋小高层国庆发售',
          contentDetails:
            '星河丹堤压轴洋房新品--澜山组团D区洋房  首页范区于10月1日全球盛放,同步认购。推售产...',
        },
        {
          id: 3,
          ctime: '2019年10月01日',
          content: '南沙星河丹堤压轴洋房新品D3栋小高层国庆发售',
          contentDetails:
            '星河丹堤压轴洋房新品--澜山组团D区洋房  首页范区于10月1日全球盛放,同步认购。推售产...',
        },
        {
          id: 3,
          ctime: '2019年10月01日',
          content: '南沙星河丹堤压轴洋房新品D3栋小高层国庆发售',
          contentDetails:
            '星河丹堤压轴洋房新品--澜山组团D区洋房  首页范区于10月1日全球盛放,同步认购。推售产...',
        },
        {
          id: 3,
          ctime: '2019年10月01日',
          content: '南沙星河丹堤压轴洋房新品D3栋小高层国庆发售',
          contentDetails:
            '星河丹堤压轴洋房新品--澜山组团D区洋房  首页范区于10月1日全球盛放,同步认购。推售产...',
        },
        {
          id: 3,
          ctime: '2019年10月01日',
          content: '南沙星河丹堤压轴洋房新品D3栋小高层国庆发售',
          contentDetails:
            '星河丹堤压轴洋房新品--澜山组团D区洋房  首页范区于10月1日全球盛放,同步认购。推售产...',
        },
        {
          id: 3,
          ctime: '2019年10月01日',
          content: '南沙星河丹堤压轴洋房新品D3栋小高层国庆发售',
          contentDetails:
            '星河丹堤压轴洋房新品--澜山组团D区洋房  首页范区于10月1日全球盛放,同步认购。推售产...',
        },
      ],
    };
  }
  componentWillMount() {
    console.log('子页面2挂载前~~~~');
  }

  componentDidMount() {
    console.log('子页面2挂载完成后~~~~');
    console.log('userId...', this.props.userId);
    // toTo楼盘动态
    const houseid = 1790;
    api
      .GetHouseDynamics(houseid)
      .then((res) => {
        // console.log('GetHouseDynamics',res.items)
        // this.setState({
        //   bannerData:res.result.items
        // })
      })
      .catch((error) => {
        // console.log('data',error)
      });
  }
  componentWillUpdate() {
    console.log('子页面2准备更新~~~~');
  }

  componentDidUpdate() {
    console.log('子页面2更新完成~~~~');
  }

  componentWillUnmount() {
    console.log('子页面2已销毁~~~~');
  }
  render() {
    console.log('子页面2挂载中~~~~');
    console.log('this.props.banner', this.props.banner);
    console.log('this.props.refreshing', this.props.refreshing);
    const TimeItem = this.state.invoice.slice(0, 3).map((item, index) => {
      return (
        <View style={styles.expressItem} key={index}>
          <View style={styles.expressRightFirst}>
            <View>
              <Text style={{color: '#202020', fontSize: 18, lineHeight: 50}}>
                {item.ctime}
              </Text>
              <Text style={{color: '#202020', fontSize: 18, lineHeight: 35}}>
                {item.content}
              </Text>
              <Text style={{color: '#888888', fontSize: 18, fontWeight: '500'}}>
                {item.contentDetails}
              </Text>
            </View>
          </View>
          {index == 0 ? (
            <View style={styles.expressLeftContainer}>
              <View style={styles.expressLeftFirst}></View>
              <View style={styles.expressLeft}></View>
            </View>
          ) : (
            <View style={styles.expressLeftContainer}>
              <View style={[styles.expressLeft]}></View>
            </View>
          )}
        </View>
      );
    });
    return <View style={styles.content}>{TimeItem}</View>;
  }
}

export default connect(
  (state) => {
    return {
      userId: state.loginReducer.userId,
      banner: state.DetailsReducer.banner,
      refreshing: state.DetailsReducer.refreshing,
      // userName: state.loginReducer.userName,
      // password: state.loginReducer.password,
    };
  },
  (dispatch) => ({
    // ...bindActionCreators(LoginActions, dispatch),
    // setAppInfo: (data) => dispatch(setAppInfo(data)),
  }),
)(TimeAxis);

const styles = StyleSheet.create({
  expressRightFirst: {
    paddingLeft: 25,
  },
  content: {
    borderLeftWidth: 1,
    borderLeftColor: '#e0e0e0',
  },
  expressItem: {
    flexDirection: 'row',
    paddingBottom: 20,
  },
  expressLeft: {
    width: 10,
    height: 10,
    borderRadius: 5,
    backgroundColor: '#e0e0e0',
    position: 'absolute',
    left: 5,
    top: 5,
  },
  expressLeftFirst: {
    width: 10,
    height: 20,
    backgroundColor: '#fff',
    position: 'absolute',
    left: 5,
    top: -20,
  },
  expressLeftContainer: {
    width: 20,
    height: 20,
    borderRadius: 10,
    backgroundColor: '#ffffff',
    position: 'absolute',
    left: -10,
    top: 15,
  },
});

子组件3 MapComponent
import React, {Component} from 'react';
import {
  TouchableOpacity,
  Image,
  StyleSheet,
  View,
  Text,
  ScrollView,
  Alert,
} from 'react-native';

const map = require('./../../resources/cHomeTab/photo/map.png');
const metro = require('./../../resources/cHomeTab/icon/metro.png');
const transit = require('./../../resources/cHomeTab/icon/transit.png');
const Restaurant = require('./../../resources/cHomeTab/icon/Restaurant.png');
const school = require('./../../resources/cHomeTab/icon/School.png');
const hospital = require('./../../resources/cHomeTab/icon/hospital.png');
const shopping = require('./../../resources/cHomeTab/icon/shopping.png');
import {unitWidth, unitHeight, height} from '../../../js/common/ScreenUtil';
// const map = require('./../../resources/cHomeTab/photo/map.png')
// const tipsIcon = require('./../../resources/cHomeTab/icon/tipsIcon.png')

export default class MapComponent extends Component {
  static defaultProps = {};

  constructor(props) {
    console.log('子页面3控制器~~~~');

    super();
    this.state = {
      // 地图选项内容
      tab: [
        {
          metroUrl: metro,
          metroText: '地铁',
        },
        {
          metroUrl: transit,
          metroText: '公交',
        },
        {
          metroUrl: Restaurant,
          metroText: '餐饮',
        },
        {
          metroUrl: school,
          metroText: '学校',
        },
        {
          metroUrl: hospital,
          metroText: '医院',
        },
        {
          metroUrl: shopping,
          metroText: '购物',
        },
      ],
    };
  }
  componentWillMount() {
    console.log('子页面3挂载前~~~~');
  }

  componentDidMount() {
    console.log('子页面3挂载后~~~~');
  }

  componentWillUpdate() {
    console.log('子页面3准备更新~~~~');
  }

  componentDidUpdate() {
    console.log('子页面3更新完成~~~~');
  }

  componentWillUnmount() {
    console.log('子页面3已销毁~~~~');
  }

  // 点击跳转查看地图
  _goToDetails = () => {
    // this.props.navigation.navigate('Map');
    this.setState({
      tab: [
        {
          metroUrl: metro,
          metroText: '地铁2',
        },
        {
          metroUrl: transit,
          metroText: '公交2',
        },
        {
          metroUrl: Restaurant,
          metroText: '餐饮2',
        },
        {
          metroUrl: school,
          metroText: '学校2',
        },
        {
          metroUrl: hospital,
          metroText: '医院2',
        },
        {
          metroUrl: shopping,
          metroText: '购物2',
        },
      ],
    });
  };

  render() {
    console.log('子页面3挂载中~~~~');
    return (
      <View style={styles.mapItem}>
        <TouchableOpacity
          onPress={() => {
            // Alert.alert(
            //   "抱歉!暂还不能使用地图",
            // );
            this._goToDetails();
          }}
          activeOpacity={0.9} //触摸时完全不透明,值越小越透明
        >
          <View style={{flexDirection: 'row'}}>
            <Image
              resizeMode="cover"
              style={{height: 382 * unitWidth, width: '100%'}}
              source={map}
            />
          </View>
          <View
            style={{
              flexDirection: 'row',
              justifyContent: 'space-between',
              paddingLeft: 40 * unitWidth,
              paddingRight: 40 * unitWidth,
              marginTop: 22 * unitWidth,
            }}>
            {this.state.tab.map((item, index) => (
              <View style={{alignItems: 'center'}} key={index}>
                <Image
                  resizeMode="cover"
                  style={{height: 40 * unitWidth, width: 40 * unitWidth}}
                  source={item.metroUrl}
                />
                <Text style={[styles.itemTitle, {color: '#000'}]}>
                  {item.metroText}
                </Text>
              </View>
            ))}
          </View>
        </TouchableOpacity>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  mapItem: {
    // flexDirection:'row',
    // justifyContent:'space-between'
  },
  itemTitle: {
    fontSize: 15,
    lineHeight: 40,
  },
  address: {
    color: '#888888',
    fontSize: 12,
    lineHeight: 25,
  },
  unitPrice: {
    color: '#eb5e36',
    fontSize: 17,
  },
});

打印结果

初始化阶段

可以看出父组件先发起初始化,执行render时,优先依次挂载完成子组件后,父组件最后才挂载完成,可以理解成两个阶段,一个是发起挂载动作(由父到子,同级组件得先等上一个同级等的子组件都发起挂载动作了才轮到),另一个是结束挂载动作(由子到父,同级组件得等上一个组件挂载完成了才能轮到,依次进行)

有一点需要注意的是初始化阶段render时componentWillReceiveProps不执行

运行中

可以看出父组件先发起更新,执行render时,优先依次更新完成子组件后,父组件最后才更新完成,可以理解成两个阶段,一个是发起挂载动作(由父到子,同级组件得先等上一个同级等的子组件都发起更新动作了才能轮到),另一个是结束更新动作(由子到父,同级组件得等上一个组件更新完成了才能轮到,依次进行)

当子组件1HouseType将shouldComponentUpdate中的返回值变为以下后,再点击后,子组件1将通过return false来定向阻止更新,自然后面的componentWillUnmount和componentWillReceiveProps也不会再继续执行了

  shouldComponentUpdate(newProps, newState) {
    console.log('子组件1更新拦截钩子shouldComponentUpdate~~~~');
    if (newProps.a == '嘿嘿') return false;
    return true; //true更新  false阻止更新
  }

此时打印结果是:

可见子组件1执行到shouldComponentUpdate钩子后便停止了!

销毁阶段

可以看出父组件先销毁,再依次销毁子组件,同级子组件得先等前面等子组件都销毁完了才销毁结束

执行次数

只执行一次: constructor、componentWillMount、componentDidMount

执行多次:render 、子组件的componentWillReceiveProps、componentWillUpdate、componentDidUpdate

有条件的执行:componentWillUnmount(页面离开,组件销毁时) 不执行的:根组件(ReactDOM.render在DOM上的组件)的componentWillReceiveProps(因为压根没有父组件给传递props)