目录
37. super() 和super(props)有什么区别?
44. useMemo, useCallback做了那些性能优化?
45.A组件是B组件的父组件,那么A组件加载完成,请详细叙述A,B组件执行流程?
1. 什么是 React ?
React 是用于构建用户界面的 JavaScript 库 , 起源于 Facebook 的内部项目,该公司对市场上所有 JavaScript MVC 框架都不满意,决定自行开发一套,用于架设自己的网站 ,React 不是一个 MVC 框架,仅仅是视图(V)层的库
2. 为什么虚拟 Dom 会提高性能 ?
虚拟 Dom 相当于在 Js 和真实 Dom 中间加了一个缓存,利用 Dom Diff 算法避免了没有必要的 Dom 操作,从而提高性能。
用 Js 对象表示真实的 Dom 结构,当状态变化的时候重新创建一个虚拟 Dom 树结构,然后用新的树和旧的树进行比较,记录两棵树差异,把所记录的差异应用到所构建的真正的 Dom 树上,视图就更新了。
3. 什么是 Jsx ?
Jsx是JavaScript的一种语法扩展,它跟模板语言很接近,但是它充分具备JavaScript的能力;
Jsx就是用来声明React当中的元素,React使用JSX来描述用户界面;
Jsx语法糖允许前端开发者使用我们最熟悉的类HTML标签语法来创建虚拟Dom在降低学习成本。
4. React 创建元素的方法 ?
let = React.createElement(type, props, children);
/**
* 主要是依赖了 React 核心库中的 React.createElement() 创建出真实 DOM
* 1. type : 类型, 组件/vnode
* 2. props: 元素 eg: id type class
* 3. children: 元素的内容
*
* view:
* 虚拟 DOM 的本质就是以一个纯 js 对象的形式去描述我们的 DOM 树.
虚拟 DOM 并不向我们的真实 DOM 对象那样, 有着庞大的属性在里面.
虚拟 DOM 本身就有几个精简的属性描述我们的 DOM 树.
虚拟 DOM 修改的时候,它会对比新旧续,vnode差异, 去做最优解, 达到最小的更新.
虚拟 DOM 是 React 给我们带来的核心价值之一
React 核心就是构建视图其实呢, React 构建出来的视图其实是一个虚拟DOM。
最后你依靠 ReactDom.render() 方法, 将虚拟dom 转化为真实dom。
*
**/
// 创建一个虚拟dom 树
console.log( React.createElement("h1", { id: "title", "hello zy" }) )
// 创建一个真实 dom 对象
console.dir(document.createElement("h1") )
console.log(document.createElement("h1") ) // <h1></h1>
React 节点熏染?
/**
主要是依赖 React-dom 的核心库, 提供了与浏览器交互的 DOM 功能, 如:dom 熏染,
ReactDOM.render(Vnode, container, [callback])
1. Vnode : 渲染的内容虚拟DOM
2. container: 要熏染内容的容器(一定是一个真实存放的dom节点)
3. callback: 熏染后的回调函数
**/
<!-- 存放虚拟节点的容器-->
<div id="root"></div>
// 构建虚拟DOM
let h1 = Reac.creacteElement("h1", { id: 'title' }, 'hello zy')
// 将虚拟DOM 转化为真实 DOM
ReactDOM.render(h1, document.querySelector("#root"),
() =>{
console.log("我是节点熏染完成之后的回调, 我是一个可选参数")
}
)
基于 React 的视图构建
<!-- 存放虚拟节点的容器-->
<body>
<div id="root"></div>
</body>
<script>
// 构建虚拟DOM
let h1 = React.creacteElement('h1', { id: 'title' }, 'hello zy')
let p = React.creacteElement('p', null, 'React 的第一个组件')
let a = React.creacteElement('a', { href: '' }, '链接1')
let a2 = React.creacteElement('a', { href: '' }, '链接2')
// 熏染 nav 的子节点
let nav = React.creacteElement('nav', null, a, a2)
let hrader = React.creacteElement('header', { id: 'i am header' }, h1, p, nav)
// 将虚拟DOM 转化为真实 DOM
ReactDOM.render(hrader , document.querySelector("#root"),
() =>{
console.log("我是节点熏染完成之后的回调, 我是一个可选参数")
}
)
</script>
// 上述的嵌套语法是比较不规范的, 我们可以使用 jsx 语法来进行简写
JSX 语法
对于开发者来说,通过 createlement 方法构建用户界面属实不太友好。
但是在 React 内部确实需要通过这个方法创建虚拟 DOM对象,如何解决这个矛盾呢?
React为 createElement 方法创造了替代语法,让开发者可以通过类似于 HTML 的语法创建用户界面,在构建应用时,再使用 babel将这种替换语法转换回 createElement 方法的调用代码。
const button = <button type="button">button</button>
React.createElement('button', ftype: "button"},"button")
JSX 是什么?
JSX是 JavaScript 编程语言的语法扩充,是由 Facebook 创建的,用于简化创建元素的代码,也就是说在 React 中,通常使用JSX 语法构建
用户界面。
const button = <button>保存</button>
ReactDoM.render(button, document.getElementById("root"))
但是这种语法浏览器是不识别的,所以我们需要借助 Babel 对其进行转换,将其转换为 React,createElement 方法的调用
// JSX-runtime 17 (新增): 可以直接将 JSX 编译为虚拟 DOM ;
// JSX 语法中支持插值表达式, JSX 中存放一个 JS 的表达式
// 表达式指的是一个可以产生值得代码组合,例如运算式, 变量, 函数, 不支持流程控制语句得输入
内容中得插值表达式可以接收值:
基本类型:
string 、number
null、undefinde、boolean, symbol 会被忽略
符合数据类型
数组 : 将数组展开 依次输出
ReactNode :
基于 createElement构建出来得dom 与 JSX-runtime 编译出得dom,
不支持对象得直接插入(哪怕这个对象在像虚拟dom, 语法也是不会被解析)
<script>
let span = <span>span</span>
let div = <header>
<div>{ span }</div>
<div>{ 2 + 2}</div>
</header>
ReactDOM.render(header, document.querySelect("#root"))
</script>
5. Class组件和函数组件区别 ?
1.语法上:
- 函数式组件是一个纯函数,它是需要接受props参数并且返回一个React元素。
- 类组件是需要继承React.Component的,而且class组件需要创建实例,通过实例调用render()并且返回React元素,语法上来讲更复杂。
2.状态管理:
- 函数式组件没有状态管理,类组件有状态管理。
3.调用方式:
- 函数式组件可以直接调用,返回一个新的React元素;
- 类组件在调用是需要创建一个实例的,然后通过调用实例中render()方法来返回一个React元素。
4.class组件是有状态的组件,可以定义state状态,函数组件无状态。
5.class组件有生命周期的,函数组件无生命周期。
6.class组件是由this对象,函数组件没有this对象。
7.class组件内部的话,render方法return返回渲染jsx模板,函数组件直接返回即可。
8.ref获取子组件的对象,class组件可以直接获取到的,函数组件无法直接获取到。
9.绑定bind改变this指向,只适用于class组件。
6. React 事件绑定方式?
React 事件绑定属性的命名采用驼峰式写法, 采用 JSX 的语法传入一个函数作为事件处理函数
事件绑定函数的方式:
1. 直接写函数名字{callback},
2. 可以使用bind方法绑定调用 {callback.bind(this)}
7. 事件处理方法this指向改变?
当我们把事件函数写成普通函数的形式时 , 调用函数使用state变量会报错,提示state变量不存在,是因为:
-
事件处理程序的函数式调用模式在严格模式下,this指向
undefined;
-
render() 函数是被组件实例调用的,因此render()函数中的this指向当前组件;
解决方法:
- 把普通函数改成箭头函数;
- 调用函数的时候使用bind方法改变this指向;
8. React事件处理方法传值?
a) 调用的时候定义一个箭头函数 函数中调用方法传递参数据
<button onClick={()=> this.del(index) }>点击</button>
b)第二种方法 bind方法传递参数
<button onClick={this.del.bind(this,index) }>点击</button>
9.React 如何获取表单数据?
- 给文本框绑定value属性,value属性绑定state中定义的变量;
- 给表单绑定onChange事件,调用定义的方法;
- 在方法中我们获取e.target.value属性,赋给value属性绑定的变量;
10. React 条件渲染方法?
- if-else的条件渲染方法;
- 条件 ? true : falues : 三元运算符进行条件渲染,可以缩短代码量;
- switch的多条件渲染效果;
- Hoc(高阶组件)条件渲染;
- 表达式 &( React元素 ) 短路逻辑
11. React 实现列表渲染?
- react中可以使用map()方法渲染列表,return对应的页面结构即可;
- React 在渲染列表时,会要求开发者为每一个列表元素指定唯一的
key
, - 我们尽量不要使用index索引值作为key,如果对数据进行:逆序添加、逆序删除等破坏顺序操作、可能会引起页面更新错误问题。
12. React 中 Key 的作用是什么?
Key是虚拟Dom对象的唯一标识,在更新显示时Key起到极其重要的作用 ,简单的来说是为了提高Diff的同级比较的效率,避免复用带来的副作用。
React采用的是自上而下更新策略,每次小的改动都会生成一个全新的虚拟Dom树,从而进行Diff比对,如不指定Key值,可能会引起本来应该更新的页面却没有更新!
13. React 组件样式的定义方式 ?
-
外联样式: 定义css文件,在组件中通过import导入css样式 -- 全局生效
import "App.css"
-
内联样式:
React推崇的是内联的方式定义样式。这样做的目的就在于让你的组件更加的容易复用
定义一个style属性,属性中定义对应的css样式即可,eg:style={{fontSize:'15px'}}。
外层花括号是语法,内层花括号是对象边界符。
14. React 中 Props校验数据类型 ?
- array(数组)
- bool(布尔值)
- function(函数)
- number(数字)
- object(对象)
- string(字符串)
15.React 中受控组件和非受控组件 ?
- 受控组件
- React控制输入表单元素的value值,称为受控组件。
- 比如,给表单元素input绑定一个onChange事件,当input状态发生变化时就会触发onChange事件,从而更新组件的state。
- React控制输入表单元素的value值,称为受控组件。
- 非受控组件
- 非受控组件指的是,表单数据由Dom本身处理。即不受setState()的控制,与传统的HTML表单输入相似。
- 在非受控组件中,可以使用一个ref来从DOM获得表单值。
16. React 中 Props和State的区别 ?
- Props 理解?
-
Props指组件间传递的一种方式,Props自然也可以传递state。
-
React数据流是自上而下、单项数据流,所以父组件向子组件进行传递数据是只读不可修改。
-
如要修改Porps中的数据,需要传递状态到父级组件节点,在父级组件中将数据修改。父级组件数据状态发生改变会触发子组件重现熏染,获取最新数据。
-
- State 理解?
- state是组件内部的状态(数据),不能够直接修改;
- 必须要通过setState来改变值的状态,从而达到更新组件内部数据的作用。
17.组件传值的方式?
父传子组件通信、子传父组件通信、 兄弟组件通信;
18.父传子通信流程?
- 在父组件中的子组件标签上绑定自定义属性,挂载传递的数据;
- 子组件中props接受传递的数据,直接使用即可;
19. 子传父通信的流程?
- 父组件中子组件标签上绑定一个属性,传递一个方法给子组件;
- 子组件中通过props属性接受这个方法,直接调用,传递相应的参数即可;
20.非父子组件通信?
- 状态提升(中间人模式)
- React中状态提升概括来说,是将多个组件需要共享的状态提升到它们最近的父组件;
- 在父组件上改变这个状态然后通过props分发给子组件;
- context状态树传参
21.Context状态树是怎么运行的?
- 在父组件中通过createContext() 创建一个空对象, 暴露并抛出该对象;
- 在父组件的最外层我们使用Provider包裹数据,通过value绑定要传递的对象数据。
- 在嵌套的子组件中,我们有两种方式获取数据:
- 我们可以使用Customer标签,在标签中绑定一个箭头函数,函数的形参context就是value传递的数据
- class组件中我们可以定义static contextType=context对象,组件中直接使用this.context获取数据。
22.React生命周期分为几个阶段?
- Mounting(挂载阶段):已插入真实 DOM
- Updating(更新阶段):正在被重新渲染
- Unmounting(卸载阶段):已移出真实 DOM
23. 简述React的生命周期函数?
- 挂载阶段:
- constructor()
- 在 React 组件挂载之前,会调用它的构造函数。
- componentWillMount()
- 即将挂载、在调用 render 方法之前调用、最后一次修改状态的机会,且在初始挂载及后续更新时都会被调用。
- render()
- 渲染页面,只能访问this.props和this.state! 不允许修改状态。(class 组件中唯一必须实现的方法)
- componentDidMount():
- 挂载完成,render()完成可以访问和修改页面DOM
- 在组件挂载后、插入 DOM 树中、立即调用
- constructor()
- 更新运行阶段:
- componentWillReceiveProps(
nextProps
):- 父组件修改属性触发,可接收到最新的props;
- 在接受父组件改变后的props需要重新渲染组件、用到的比较多;
- 外部组件传递频繁的时候会导致效率比较低。
- shouldComponentUpdate(nextProps,nextState)
- 用于控制组件重新渲染的生命周期,state发生变化,组件会进入重新渲染的流程。
- 默认返回 true,执行更新,返回false会阻止render()调用在这可以阻止组件的更新。
- 这是一个可以做性能优化的生命周期函数;
- render()
- 渲染页面,只能访问this.props和this.state,不允许修改状态
- class 组件中唯一必须实现的方法。
- componentWillUpdate():
- 即将更新,不能修改属性和状态,强行修改会导致内存泄露死循环
- shouldComponentUpdate()返回true以后,组件进入重新渲染完成之前进入这个函数。
- componentDidUpdate(prevProps, prevState,value)
- 每次state改变并重新渲染页面后都会进入这个生命周期;
- 完成更新,可以修改dom,第三个参数是配合新的生命周期使用;
- componentWillReceiveProps(
- 卸载或销毁阶段
- componentWillUnmount ()
- 此处完成组件的卸载和数据的销毁。清除定时器、消息订阅与发布等操作
- componentWillUnmount ()
24. React旧生命周期有哪些问题?
- componentWillMount ,在ssr(服务端渲染)中 这个方法将会被多次调用, 所以会重复触发多遍,同时在这里如果绑定事件,将无法解绑,导致内存泄漏 , 变得不够安全高效逐步废弃。
- componentWillReceiveProps 外部组件多次频繁更新传入多次不同的 props,会导致不必要的异步请求
- componetWillupdate, 更新前记录 DOM 状态, 可能会做一些处理,与componentDidUpdate相隔时间如果过长, 会导致状态不太信,不够精准使数据产生偏差
- 注:在使用以上三个被逐步废弃的生命周期需要加上UNSAFE_前缀
25. React新生命周期有哪些改变?
- static getDerivedStateFromProps(nextProps)
- 第一次的初始化组件以及后续的更新过程中(包括自身状态更新以及父传子) ,返回一对象作为新的state,返回null则说明不需要在这里更新state。
- 相当于替代了componentWillMount和componentWillReceiveProps
-
getSnapshotBeforeUpdate
-
取代了 componetWillUpdate()
-
触发时间为update发生的时候,在render之后dom渲染之前返回一个值,作为componentDidUpdate的第三个参数。
-
避免和CompoentDidUpdate函数中获取数据不一致的问题。
-
26. react的路由几种模式,是什么?
- Hash路由模式:用的是HashRouter组件
- 历史路由模式: 用的是BrowserRouter组件绑定
27. react路由常用的组件有哪些?
- HashRouter或BrowserRouter配置路由模式
- Route 定义路由组件映射关系
- Redirect 设置路由重定向
- NavLink 或者Link 页面路由跳转
- Switch 路由匹配,当path匹配到一个component之后,将不会再想下继续匹配,提高了程序效率
28. react路由传参的方式有哪些?
- 隐士参数传递
- this.props.history.push({ pathname : '/user' ,query : {id:100}})
- this.props.location.query.id 获取query传递的参数据,刷新数据不在
- 路由导航传递
- this.props.history.push({ pathname:'/user',state:{id: 1000 } })
- this.props.location.state.id 获取state的数据,刷新数据还在
- url传参方式
- history.location.search获取数据比较麻烦,得自己解析
- 动态路由定义
/detail/:id
=>/detail/100
- location.match.params中接受的参数是 {id:100}
29. react路由跳转的方式有哪些?
- 声明式导航
- 使用NavLink或者Link跳转, to属性后面跟字符串或者跟对象
- 编程式导航跳转
- props.history.push(url) 跳转页面可以返回上一页,保留历史记录
- props.history.replace(url) 跳转页面,清空历史记录
- props.history.go(num) 返回第几个页面
30. react路由嵌套如何配置?
- 配置父组件的路由地址,在父组件中配置子组件的路由映射关系
- 关闭父组件路由配置exact属性,避免精准匹配
- 父组件路由地址作为子组件路由地址的开始的一部分。比如父组件是/index 子组件应该是/index/子组件地址
31. withRouter是干什么的?
不是所有组件都直接与路由相连(比如拆分的子组件)的,当这些组件需要路由参数时,使用
withRouter就可以给此组件传入路由参数,将react-router的history、location、match三个对象传入
props对象上,此时就可以使用this.props.history跳转页面了或者接受参数了。
32. 什么是Redux?
在react中每个组件的state是由自身进行管理,包括组件定义自身的state、组件之间的通信通过props传递、使用Context实现数据共享等,如果让每个组件都存储自身相关的状态,理论上来讲不会影响应用的运行。
在开发及后期我们将比较难以维护,所以我们可以把数据进行集中式的管理,redux就是一个实现上述集中管理的容器的工具,
redux
并不是只应用在react
中,还与其他界面库一起使用,如Vue。
33. Redux的三大原则?
- state数据必须是单一数据源
- redux中的state数据必须 是只读的,只能通过dispatch调用actions修改
- Reducer必须使用纯函数来执行修改
34. redux的执行原理?
React的组件需要获取或者修改页面的数据,通过dispatch方法调用actions进入到Reducer函数中。修改state的数据内容,state更新后,通知组件更新页面即可。
35. redux的使用步骤?
- 创建一个store文件夹,新建一个index.js文件
- 文件中导入redux的createStore方法,用于创建公共数据区域
- 创建一个reducer纯函数,接受两个参数state,actions分别表示分别表示数据和操作state的方法,返回state数据给组件页面
- 把reducer作为createStore的参数抛出
- 在需要使用的页面导入store文件,通过store.getState获取数据,通过store.dispatch触发action修改state数据
- store.subscrible 方法监听 store 的改变,避免数据不更新
36. state和props有什么区别?
相同点
- 两者都是 JavaScript 对象。
- 两者都是用于保存信息。
- props 和 state 都能触发渲染更新。
区别
- props 是外部传递给组件的,而 state 是在组件内被组件自己管理的,一般在 constructor 中初始化。
- props 在组件内部是不可修改的,但 state 在组件内部可以进行修改
- state 是多变的、可以修改
37. super() 和super(props)有什么区别?
在 React 中,类组件基于 ES6,所以在 constructor 中必须使用 super
在调用 super 过程,无论是否传入 props,React 内部都会将 porps 赋值给组件实例 porps 属性中
如果只调用了 super(),那么 this.props 在 super() 和构造函数结束之间仍是 undefined
38. 说说 React中的setState执行机制?
一个组件的显示形态可以由数据状态和外部参数所决定,而数据状态就是state, 当需要修改里面的值的状态需要通过调用setState来改变,从而达到更新组件内部数据的作用。
setState第一个参数可以是一个对象,或者是一个函数,而第二个参数是一个回调函数,用于可以实时的获取到更新之后的数据。
在使用setState更新数据的时候,setState的更新类型分成:同步更新,异步更新。
在组件生命周期或React合成事件中,setState是异步。
在setTimeout或者原生dom事件中,setState是同步。
对同一个值进行多次 setState, setState 的批量更新策略会对其进行覆盖,取最后一次的执行结果。
39. React的事件机制总结?
React事件机制总结如下:
- React 上注册的事件最终会绑定在document这个 DOM 上,而不是 React 组件对应的 DOM(减少内存开销就是因为所有的事件都绑定在 document 上,其他节点没有绑定事件)
- React 自身实现了一套事件冒泡机制,所以这也就是为什么我们 event.stopPropagation()无效的原因。
- React 通过队列的形式,从触发的组件向父组件回溯,然后调用他们 JSX 中定义的 callback
- React 有一套自己的合成事件 SyntheticEvent。
40. 说说对React refs 的理解?应用场景?
创建ref的形式有三种?
- 传入字符串,使用时通过 this.refs.传入的字符串的格式获取对应的元素。
- 传入对象,对象是通过 React.createRef() 方式创建出来,使用时获取到创建的对象中存在 current 属性就是对应的元素。
- 传入hook,hook是通过 useRef() 方式创建,使用时通过生成hook对象的 current 属性就是对应的元素。
- 在某些情况下,我们会通过使用refs来更新组件,但这种方式并不推荐,更多情况我们是通过props与state的方式进行去重新渲染子元素
但下面的场景使用refs非常有用!
- 对Dom元素的焦点控制、内容选择、控制
- 对Dom元素的内容设置及媒体播放
- 对Dom元素的操作和对组件实例的操作
- 集成第三方 DOM 库
41. 说说对高阶组件的理解?应用场景?
定义:
一个函数的参数是一个函数,或者 函数的返回值是一个函数,我们称这类函数是高阶函数。
什么是React高阶组件:一个组件的参数是组件,并且返回值是一个组件,我们称这类组件为高阶组件。
常见的高阶组件:
withRouter() memo() react-redux中connect方法是高阶组件
实现方式
React 中的高阶组件主要有两种形式:属性代理 和 反向继承。
属性代理: 是 一个函数接受一个 WrappedComponent 组件作为参数传入,并返回一个继承了 React.Component 组件的类,且在该类的 render() 方法中返回被传入的 WrappedComponent 组件。
反向继承:是 一个函数接受一个 WrappedComponent 组件作为参数传入,并返回一个继承了该传入 WrappedComponent 组件的类,且在该类的 render() 方法中返回 super.render() 方法。
42. 说说对Redux中间件的理解?常用的中间件有哪些?
Redux中,中间件就是放在就是在dispatch过程,在分发action进行拦截处理
前面我们了解到了Redux整个工作流程,当action发出之后,reducer立即算出state,整个过程是一个同步的操作。
那么如果需要支持异步操作,或者支持错误处理、日志监控,这个过程就可以用上中间件,其本质上一个函数,对store.dispatch方法进行了改造,在发出 Action和执行 Reducer这两步之间,添加了其他功能。
常用的redux中间件,如:
redux-thunk:用于异步操作
redux-logger:用于日志记录
中间件都需要通过applyMiddlewares进行注册,作用是将所有的中间件组成一个数组,依次执行然后作为第二个参数传入到createStore中
const store = createStore(
reducer,
applyMiddleware(thunk, logger)
);
43. React中常见的Hooks方法有哪些?
-
useState
useState()用于为函数组件引入状态。在useState()中,数组第一项为一个变量,指向状态的当前值。类似this.state,第二项是一个函数,用来更新状态,类似setState
-
useEffect
useEffect()接受两个参数,第一个参数是你要进行的异步操作,第二个参数是一个数组,用来给出Effect的依赖项。只要这个数组发生变化,useEffect()就会执行
-
useRef
相当于class组件中的createRef的作用,ref.current获取绑定的对象
-
useContext
接受context状态树传递的数据内容
-
useReducer
接受reducer函数和状态的初始值作为参数,返回一个数组,其中第一项为当前的状态值,第二项为发送action的dispatch函数
-
userMemo useCallback
useMemo 和 useCallback接收的参数都是一样,第一个参数为回调,第二个参数为要依赖的数据
共同作用:仅仅依赖数据发生变化, 才会调用,也就是起到缓存的作用。useCallback缓存函数,useMemo 缓存返回值。
44. useMemo, useCallback做了那些性能优化?
useMemo 主要缓存复杂运算的数据的结果,第二个参数,定义监听的变量,需要返回一个结果。
当父组件的组件更新的时候会导致子组件的重新渲染,但是如果父组件的更新的数据没有传递给子组件的话,这个时候如果还让子组件重新渲染的化,就会导致组件的更新的性能消耗比较大。
所以说这个时候我们可以使用useMemo, 或者React中内置的memo方法对子组件进行缓存,这样的话只有父组件更新跟子组件相关联的数据的时候才会导致子组件的重新渲染,从而提高组件的渲染性能。
但是如果我们给子组件传递方法的时候,上面memo方法的缓存就不起作用了,原因是父组件没更新一次会导致方法的重新调用,进而导致子组件的重新更新,所以这个时候我们可以使用useCallback对传递的方法进行缓存,监听数据更新后才会重新调用方法,从而提高组件的渲染性能。
45.A组件是B组件的父组件,那么A组件加载完成,请详细叙述A,B组件执行流程?
执行A组件的constructor, componentWillMount, render方法
执行B组件的 constructor, componentWillMount, render componentDidMount方法
在执行A的的componentDidMount方法,更新的方法类比