前段时间参加了一场知乎Live,老师解析得很透彻,昨天仔细又听了几遍,写个笔记分享出来:
理解React的工作原理
本质:
-
UI = f(data)
- 数据(props & state)驱动function改变UI
- 如何实现,对大部分dev来说不care,virtual Dom, DIff函数
- virtual Dom如何比对:
- 动态使用子组件的时候一定要使用key
- diff算法:用来比对文件前后的变化(类似git diff,git diff的算法时间复杂度O(n^3))
- react放弃比对(如下图:A移动到B),取其次:删除A,R上增加X,B上增加A(O(n)的时间复杂度,从根节点往下比对,先比较类型,类型不同,会触发Mount,类型相同会触发update)
-
key的作用:由于react使用了另一种比对方式,当遇到如下场景,会产生很多不必要的渲染消耗,动态产生的子组件需要key这个prop:
- 1.key的值在兄弟节点之间唯一,2.key的值在渲染的过程中要稳定
一切都是组件
组件化:软件都像乐高积木一样
组件化的模型不需要关心别人的积木怎么搭
react中组件可以做任何事情声明式编程 (Declarative Programming)
实现了申明式:很少去调用react的api,声明式,而不是主动去调用API改变
冒泡:拍桌子-》拍大楼-》拍地球
jq,命名式设计,对冒泡的处理:bind(), live(), delegate(),on()
JSX的优势与局限
争议:HTML内容,CSS样式,JS动态。全都放到一个文件里
结论:应该遵循相关逻辑code应该放到一起的原则
CSS侵入性:引入一个class影响全局css class
麻烦:jsx需要babel,又需要webpack
render函数:
1.花括号里不能写语句,只能写表达式
2.纯函数,不要使用push,reverse。。
使用props还是state
react一切皆组件,小组件组成大组件
props:组件外部传入的数据
state:组件内部的状态,一个组件的state可以作为
传给子组件的数据来源,一个组件改变自己的状态只能改变state,绝对不能修改传入的props
尽量构建一个state很少的组件(无状态)尽量使用props解决问题
生命周期
三种过程:
- mount:从无到有
- update: 因为状态改变或者属性改变,分为state
change引发的,和props引发的 - unmount:从有到无的过程
mount过程:
getDefaultProps(默认props)
getInitialState(初始的state)
componentWillMount(mount之前做的事情)
render(执行这个改变state与props)
componentDidMount(只在浏览器端执行,服务器端吐出来的是字符串)
因state改变引发的update过程:
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
因父组件想要render这个组件改变引发的update过程:
componentWillReceiveProps
shouldComponentUpdate(可以截胡,节省不必要的渲染性能开销,提高react性能)
componentWillUpdate
render
componentDidUpdate
为什么尽量使用无状态组件
组件分解,遵守函数式编程的原则,大部分组件以纯函数形式表现(单元测试,少bug)
组件分类为:有状态+无状态有些宽泛,也可以有组件什么都不画
import React from 'react';
export default class HeartBeat extends React.Component {
render() {
return null;
}
componentDidMount() {
this.timer = setInterval(() => {
fetch('/api/v1/heartbeat');
}, 5000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
}
创建高阶组件(HoC,Higher-Order Component)
HOC应用场景:如果功能在组件之间可以共享,那么创建HOC
包含方式创建:
const HoC = (WrappedComponent) => {
const WrappingComponent = (props) => (
<div className="foo">
<WrappedCompoent {...props} />
</div>
);
return WrappingComponent;
};
继承方式创建(不推荐):
const HoC = (WrappedComponent) => {
class WrappingComponent extends WrappendComponent {
render() (
const {user, ...otherProps} = this.props;
this.props = otherProps;
return super.render();
}
}
return WrappingComponent;
};
一个HOC没有说只有一个组件类作为参数:
const HoC = (WrappedComponent, LoginView) => {
const WrappingComponent = () => {
const {user} = this.props;
if (user) {
return <WrappedComponent {...this.props} />
} else {
return <LoginView {...this.props} />
}
};
return WrappingComponent;
};
组件之间通讯
对react来说,组件间通信的确是一件棘手的事情,所以在构建大型应用的时候,我们不得不引入第三方的东西来处理(比如:redux)
- 父子通信关系
方法一:- 父传子:props直接传
- 子传父:父通过props传递函数让子调用来影响父
方法二: - ref(不推荐)
-
callback(promise)
-
兄弟通信关系
父组件造两个函数传给两个子组件,父组件桥接作用,让两个子组件通信(很笨拙)
-
任意位置两个组件通信
全局变量+emmit