###react的componentWillReceiveProps(nextProps) {} 生命周期
在react的componentWillReceiveProps(nextProps)生命周期中,可以在子组件的render函数执行前获取新的props,从而更新子组件自己的state。
这样的好处是,可以将数据请求放在这里进行执行,需要传的参数则从componentWillReceiveProps(nextProps)中获取。而不必将所有的请求都放在父组件中。于是该请求只会在该组件渲染时才会发出,从而减轻请求负担。
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul> ### 可以用以下JavaScript对象来表示:
{
tag: 'ul',
children: [{
tag: 'li', children: ['Item 1'],
tag: 'li', children: ['Item 2'],
tag: 'li', children: ['Item 3']
}]
} ### 这样可以避免直接频繁地操作DOM,只需要在js对象模拟的虚拟DOM进行比对,在将更改的部分应用到真实的DOM树上,并且虚拟DOM元素对象相对于真是DOM元素对象较轻(属性,方法较少) ## 五、React组件性能优化(组件通信) ### 方式一、通过props传递 - 共同的数据放在父组件上,特有的数据放在自己组建内部(state中) - 通过props可以传递一般数据和函数数据,只能一层一层传递 - 一般数据---》父组件传递数据给子组件---》子组件读取数据 - 函数数据---》子组件传递数据给父组件---》子组件调用函数 ### 方式二、使用消息订阅(subscribe)-发布(publish)机制 - 工具库:PubSubJS - 下载: npm install pubsub-js --save - 使用:
- import PubSub from 'pubsub-js' //引入
- PubSub.subscribe('delete', function(data){ }) //订阅
- PubSub.publish('delete', data) //发布消息 ### 方式三、redux - 集中式管理react应用中多个组件共享的状态,从后台获取的数据也交给redux管理 ## 六、React组件 ### ReactDOM.render(<MyComponent1/>,document.getElementById('example1')) **render()渲染组件标签的基本流程:** * 1.找到 MyComponent2 组件类,先创建一个实例 * 2.再调用render方法,得到返回值(虚拟DOM) * 3.将组件类的返回值(虚拟DOM)转化为真实dom元素 * 4.插入到指定的页面元素内部 ## 1.无状态组件(简单组件)也叫工厂函数组件 ### 无状态组件其实本质上就是一个函数,只需要传入props,没有state,也没有生命周期方法。组件本身对应就是render方法。例子如下:
function Title({color = 'red', text = '标题'}) {
let style = {
'color': color
}
return (
<div style = {style}>{text}</div>
)
} ### 无状态组建不会创建对象,所以比较省内存。没有复杂的生命周期方法调用,所以流程比较简单。没有state,也不会重复渲染。它本质上就是一个函数而已。 ### 对于没有状态变化的组件,React建议我们使用无状态组件,总之,能用无状态组件的地方,就用无状态组件。 ## 2.ES6类组件(复杂组件)
//1.定义组件
class MyComponent2 extends React.Component{
//这里的render是回调函数
render (){
//重写render方法(父类React.Component中本来就有一个render方法)
console.log(this);
//MyComponent2 {props: {…}, context: {…}, refs: {…}, updater: {…}, _reactInternalFiber: FiberNode, …}
return ( //返回虚拟dom元素
<div>
<h2>ES6类组件(复杂组件)</h2> //最多有一个
</div>
)
}
} ##注意: - 组件名必须首字母大写 - 虚拟DOM元素最多只能有一个根元素 - 虚拟DOM元素必须有结束标签,单标签必须有自结束标签:`<input/>` ## 3.高阶组件 ### 高阶组件(HOC)是函数接受一个组件,返回一个新组件。其前身其实是用ES5创建组件时可用的mixin方法,但是在react版本升级过程中,使用ES6语法创建组件时,认为mixin是反模式,影响了react架构组件的封装稳定性,增加了不可控的复杂度,逐渐被HOC所替代。 实现高阶组件的方式有: ### 属性代理:
import React, { Component } from 'React';
//高阶组件定义
const HOC = (WrappedComponent) =>
class WrapperComponent extends Component {
render() {
return <WrappedComponent {...this.props} />;
}
}
//普通的组件
class WrappedComponent extends Component{
render(){
//....
}
}
//高阶组件使用
export default HOC(WrappedComponent) ### 反向继承:
反向继承是指返回的组件去继承之前的组件(这里都用WrappedComponent代指)
const HOC = (WrappedComponent) =>
class extends WrappedComponent {
render() {
return super.render();
}
} #### 我们可以看见返回的组件确实都继承自WrappedComponent,那么所有的调用将是反向调用的(例如:super.render()),这也就是为什么叫做反向继承。 ## 七、React事件与传统事件有什么区别? ## 1.React事件 #### React 实现了一个“合成事件”层(synthetic event system),这个事件模型保证了和 W3C 标准保持一致,所以不用担心有什么诡异的用法,并且这个事件层消除了 IE 与 W3C 标准实现之间的兼容问题。 ## 2.'合成事件'还提供了额外的好处:事件委托 #### 合成事件”会以事件委托(event delegation)的方式绑定到组件最外层的元素,并且在组件卸载(unmount)的时候自动销毁绑定的事件 ## 八、React的生命周期图  ## 生命周期的理解
1) 组件对象从创建到死亡它会经历特定的生命周期阶段
2) React组件对象包含一系列的勾子函数(生命周期回调函数), 在生命周期特定时刻回调
3) 我们在定义组件时, 可以重写特定的生命周期回调函数, 做特定的工作 ## 生命周期流程
a. 第一次初始化渲染显示: ReactDOM.render() 四步
* constructor(): 创建对象初始化state
* componentWillMount() : (将要挂载)将要插入回调
* render() : 用于插入虚拟DOM回调
* componentDidMount() : (挂载完成)已经插入回调
b. 每次更新state: this.setSate() 三步
* componentWillUpdate() : 将要更新回调
* render() : 更新(重新渲染)
* componentDidUpdate() : 已经更新回调
c. 移除组件: ReactDOM.unmountComponentAtNode(containerDom) 一步
* componentWillUnmount() : 组件将要被移除回调 ## 九、React中调用setState之后发生了什么事情? ### 第一步:React会将当前传入的参数对象与组件当前的状态合并,然后触发调和过程,在调和的过程中,React会以相对高效的方式根据新的状态构建React元素树并且重新渲染整个UI界面。 ### 第二步:React得到的元素树之后,React会自动计算出新的树与老的树的节点的差异,然后根据差异对界面进行最小化的渲染,在React的差异算法中,React能够精确的知道在哪些位置发生看改变以及应该如何去改变,这样就保证了UI是按需更新的而不是重新渲染整个界面。 ## 十、React中Element(虚拟DOM对象)与Component的区别? - 1.自定义标签名(除了html标签名):组件标签 - 2.html的标签名:虚拟DOM标签 - 3.组件可以生成虚拟DOM对象 - 4.组件它最终返回的是虚拟DOM对象的集合 - 5.ReactElement是描述屏幕上所见的内容的数据结构,是对于UI的对象的表述 - 6.ReactComponent则是可以接收参数输入并且返回某个ReactElement的函数或者类 ## 十一、在什么情况下会优先选择使用ClassComponent而不是FunctionalComponent? - 定义复杂组件的时候 - 定义组件内部需要设置状态的时候 ## 十二、受控组件(Controlled Component) 与 非受控组件(Uncontrolled Component) 之间的区别是什么? ## 受控组件定义上更多的是针对表单项 表单中阻止浏览器默认行为:event.preventDefault() - 受控组件: 将表单项内的数据交由组件内部管理,通常是放在组件的state状态中,通过修改状态去控制表单项的显示(表单输入数据能自动收集状态) - 非受控组件内部的内容通常直接放在DOM元素中,通常通过refs去管理(需要时才手动读取表单输入框中的数据) - 看上去非受控组件比受控组件更为简单,但还是提倡使用受控组件,因为**页面与数据分离** ## 十三、React中keys的作用是什么? - key是react中列表元素对应的唯一值。 - Keys 是React在操作列表中元素被修改,添加,或者删除的辅助标识。 - 在开发过程中,我们需要保证某个元素的key 在其同级元素中具有唯一性,在ReactDiff算法中React会借助元素的Key值来判断该元素是新创建的还是被移动而来的元素,React会保存这个辅助状态,从而减少不必要的元素渲染.此外,React还需要借助Key值来判断元素与本地状态的关联关系,因此我们在开发中不可忽视Key值的使用。 - <font color=red>平时设定key的唯一值得时候使用的遍历数组结构的index,注意当新添加的元素中有表单项且变化之前表单项有内容的时候,表单项会根据key的值记录变化之前内部输入的值,此时应该自己去设定key的唯一值</font> ## 十四、redux管理数据的机制 ### 1)redux是一个独立专门用于做状态管理的JS库(不是react插件库) ### 2)它可以用在react, angular, vue等项目中, 但基本与react配合使用 ### 3)作用: 管理react应用中多个组件共享的状态 ### 4)Redux核心思想:store对象负责调度管理状态并和组件进行对接 ### 5)Redux核心管理流程:
Redux初始化的时候调用reducer获取初始化状态,
当组件的状态需要改变的时候可以将需要改变的状态方式和内容通知redux,
redux接收到信号后调用dispatch去分发一个对象,该对象为action对象,
其中包含的了改变状态的方式和参与改变状态的数据(可能没有数据),
当dispatch分发对象之后会触发reducer函数的调用,
reducer函数是专门用来服务于stroe对象的,reducer函数处理完状态数据,
将数据交给store对象,store对象再将状态数据交给对应的组件,从而进行对应的页面渲染。 
<input :value=”something” @input=”something = $event.target.value”>
也就是说,你只需要在组件中声明一个name为value的props,并且通过触发input事件传入一个值,就能修改这个value。
categorysArr () {
const {categorys} = this
const arr = []
let smallArr = []
categorys.forEach(c => {
// 将全新的小数组保存到大数组中
if(smallArr.length===0) {
arr.push(smallArr)
}
// 将当前分类保存到小数组
smallArr.push(c)
// 如果刚好满了, 为后面创建一个新的小数组
if(smallArr.length===8) {
smallArr = []
}
})
return arr
}
}