一、react 生命周期:
组件初始化阶段:
这个阶段没有具体的生命周期函数,在类组件里面,继承了react component,才有了render函数,生命周期才可以使用,这就说明函数组件为什么不能使用这些方法的原因。
挂载阶段:
componentWillMount:在第一次渲染时的第一个运行的生命周期,可以修改state,无法判断传入参数,可以修改props,修改了props以后重新运行生命周期。
render:可以修改state和props,需要重新执行生命周期。
conponentDidMount:在第一次渲染时,渲染结束运行的生命周期,修改state很安全,可以修改props,重新运行生命周期。
更新阶段:
componentWillReceiveProps:在运行props时运行的生命周期,可以修改state或者props。如果修改state以后,之后的生命周期传入的state参数会更新。修改props在这个生命周期里面很危险,会重新运行一遍生命周期。
shouldComponentUpdate:在更新props或者state时运行的生命周期,返回true或者fase,一旦返回的是false,接下来的生命周期都不再运行。这里可以修改props或者state,但是很危险,都是重新运行一遍生命周期。
componentWillUpdate:在修改props或者state即将渲染时运行的生命周期。可以修改state或者props,但是很危险,都是重新运行一遍生命周期。
render
componentDidUpdate:在修改props或者state渲染完render运行的生命周期。可以修改state或者props,但是很危险,都是重新运行一遍生命周期。
卸载阶段:
componentWillUnmount:卸载
新的生命周期:
getDerivedStateFromProps:
无论什么情况下都是第一个运行的生命周期。这个生命周期是类的静态方法,这个函数返回一个对象(必须得是对象或者数组)来更新state的数据。更新当前的state和新的即将要更新的新state。不能访问实例,所以不能修改state和props。但是也可以给全局增加一个变量,在componentDidMount的时候赋值实例。这样子可以修改props和state,但是很危险。这个生命周期在第一次渲染时代替了componentWillMount。在修改state代替了componentWillUpdate。在修改props时代替了componentWillReceiveProps和componentWillUpdate生命周期。
getSnapshotBeforeUpdate:
在更新props或者state时,在rander渲染完之后在componentDidUpdate之前时运行这个生命周期。作用是返回一个数据,作为componentDidUpdate的第三个参数传入。可以修改state和props,但是很危险的操作,都是重新运行一遍生命周期。更新state或者props时,在render和componentDidUpdate之间加了这个生命周期。
componentDidCatch:抓捕错误的生命周期
二、组件通信:
- 父组件向子组件通讯: 父组件可以向子组件通过传 props 的方式,向子组件进行通讯;
- 子组件向父组件通讯: props+回调的方式,父组件向子组件传递props进行通讯,此props为作用域为父组件自身的函数,子组件调用该函数,将子组件想要传递的信息,作为参数,传递到父组件的作用域中;
- pubsub可以采用发布订阅的方式实现组件间的传值;
import Pubsub from‘pubsub-js’ Pubsub.publish(‘username’,val)//发布 Pubsub.subscribe(‘username’,(msg,data)=>{}//data是你要拿回来的数据。
- 兄弟组件通信: 找到这两个兄弟节点共同的父节点,结合上面两种方式由父节点转发信息进行通信;
- 跨层级通信: Context设计目的是为了共享那些对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言,对于跨越多层的全局数据通过Context通信再适合不过。 context使用了Provider和Customer模式,和react-redux的模式非常像。在顶层的Provider中传入value, 在子孙级的Customer中获取该值;
- 发布订阅模式: 发布者发布事件,订阅者监听事件并做出反应,我们可以通过引入event模块进行通信;
- 全局状态管理工具: 借助Redux或者Mobx等全局状态管理工具进行通信,这种工具会维护一个全局状态中心Store,并根据不同的事件产生新的状态;
三、虚拟Dom和真实Dom的区别:
- 虚拟dom不会进行排版与重绘操作
2. 虚拟dom进行频繁修改,然后一次性比较并修改真实dom中需要改的部分,最后在真实dom中进行排版与重绘
3. 真实dom频繁修改效率极低.
4. 虚拟dom有效降低大面积的重绘和排版
四、虚拟dom的优缺点:
优点:
1. 保证性能下限: 虚拟DOM可以经过diff找出最小差异,然后批量进行patch,这种操作虽然比不上手动优化,但是比起粗暴的DOM操作性能要好很多,因此虚拟DOM可以保证性能下限;
2. 无需手动操作DOM: 虚拟DOM的diff和patch都是在一次更新中自动进行的,我们无需手动操作DOM,极大提高开发效率 跨平台: 虚拟DOM本质上是JavaScript对象,而DOM与平台强相关,相比之下虚拟DOM可以进行更方便地跨平台操作,例如服务器渲染、移动端开发等等。
缺点:
无法进行极致优化: 在一些性能要求极高的应用中虚拟DOM无法进行针对性的极致优化,比如VScode采用直接手动操作DOM的方式进行极端的性能优化
五、虚拟dom实现原理:
- 虚拟DOM本质上是JavaScript对象,是对真实DOM的抽象;
- 状态变更时,记录新树和旧树的差异
- 最后把差异更新到真正的dom中
六、redux:
1、什么是redux:
redux是一个流行的javaScript框架,为应用框架提供一个可预测的状态容器,redux基于简化版本的Flux框架,Flux是Faceboox开发的一个框架,在标准的MVC框架中,数据可以在UI组件和存储之间双向流动,而redux严格限制了数据只能在一个方向流动。
2、redux 三大原则:
(1)单一数据源
整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
这让同构应用开发变得非常容易。来自服务端的 state 可以在无需编写更多代码的情况下被序列化并注入到客户端中。由于是单一的 state tree ,调试也变得非常容易。在开发中,你可以把应用的 state 保存在本地,从而加快开发速度。此外,受益于单一的 state tree ,以前难以实现的如“撤销/重做”这类功能也变得轻而易举。
(2) State 是只读的
唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
这样确保了视图和网络请求都不能直接修改 state,相反它们只能表达想要修改的意图。因为所有的修改都被集中化处理,且严格按照一个接一个的顺序执行,因此不用担心 race condition 的出现。 Action 就是普通对象而已,因此它们可以被日志打印、序列化、储存、后期调试或测试时回放出来。
(3)使用纯函数来执行修改
为了描述 action 如何改变 state tree ,你需要编写 reducers。
Reducer 只是一些纯函数,它接收先前的 state 和 action,并返回新的 state。刚开始你可以只有一个 reducer,随着应用变大,你可以把它拆成多个小的 reducers,分别独立地操作 state tree 的不同部分,因为 reducer 只是函数,你可以控制它们被调用的顺序,传入附加数据,甚至编写可复用的 reducer 来处理一些通用任务,如分页器。
3、redux中间件:
中间件提供第三方插件的模式,自定义拦截 action -> reducer 的过程。变为 action —> middlewares —> reducer 。这种机制可以让我们改变数据流,实现如异步 action ,action 过滤,日志输出,异常报告等功能。
常见的中间件:
redux-logger:提供日志输出
redux-thunk:处理异步操作
redux-promise:处理异步操作,actionCreator的返回值是promise
4、redux的优缺点:
1.一个组件所需要的数据,必须由父组件传过来,而不能像flux中直接从store取。
2.当一个组件相关数据更新时,即使父组件不需要用到这个组件,父组件还是会重新render,可能会有效率影响,或者需要写复杂的shouldComponentUpdate进行判断。
七、高阶组件:
高阶组件是重用组件逻辑的高级方法,是一种源于 React 的组件模式。 HOC 是自定义组件,在它之内包含另一个组件。它们可以接受子组件提供的任何动态,但不会修改或复制其输入组件中的任何行为。你可以认为 HOC 是“纯(Pure)”组件。
可以用于:
- 代码重用,逻辑和引导抽象
- 渲染劫持
- 状态抽象和控制
- Props 控制
八、react-hook
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
import React ,{useState} from‘react’
useState:函数组件里面没有state,所以我们使用useState,只接受一个参数,就是该state属性的初始值,它会返回一个数组,里面包含两个值,第一个值是初始值,第二个用来更改初始值。
useEffect:函数式组件没有生命周期,使用useEffect来替代componentDidMount和componentDidUpdate。有两个参数,第一个是一个回调函数,第二个是空数组。如果第二个数组为空数组,就会在初始化执行完成之后,执行一次,相当于componentDidMount,数组有内容,会根据数组内容改变去执行前面的回调函数。相当于componentDidUpdate生命周期。
userContext:组件之间共享状 https://blog.csdn.net/weixin_43606158/article/details/100750602
useReducer:相当于简单的redux。接收两个参数,第一个参数是一个回调函数,里面接收一个state数据,以及action,通过dispatch来更改内容。第二个参数是一个初始值。
useCallback:传入两个参数,第一个是回调函数,第二个是依赖,这个回调函数只在某个依赖改变时才会更新。
useMemo:可以优化用以优化每次渲染的耗时工作。
useRef:它可以用来获取组件实例对象或者是DOM对象,来跨越渲染周期存储数据,而且对它修改也不会引起组件渲染。
九、react中key的重要性:
key 用于识别唯一的 Virtual DOM 元素及其驱动 UI 的相应数据。它们通过回收 DOM 中当前所有的元素来帮助 React 优化渲染。在虚拟dom节点中赋予key值,会更加快速的拿到需要的目标节点,不会造成就地复用的情况,对于节点的把控更加精准。
十、react合成事件:
采用事件冒泡的形式冒泡到document上面,然后React将事件封装给正式的函数处理运行和处理。围绕浏览器原生事件充当跨浏览器包装器的对象。它们将不同浏览器的行为合并为一个 API。这样做是为了确保事件在不同浏览器中显示一致的属性。
十 一、react-mobx
MobX是响应式编程,实现状态的存储和管理。使用MobX将应用变成响应式可归纳为三部 曲:
- 定义状态并使其可观察
- 创建视图以响应状态的变化
- 更改状态
- observable是将类属性等进行标记,实现对其的观察。三部曲中的第一曲,就是通过Observable实现的。
- 通过action改变state。三部曲中的第一曲通过action创建一个动作。action函数是对传入的function进行一次包装,使得function中的observable对象的变化能够被观察到,从而触发相应的衍生。
mobx api
(1)、computed:计算值(computed values)是可以根据现有的状态或其它计算值衍生出的值。简单理解为对可观察数据做出的反应,多个可观察属性进行处理,然后返回一个可观察属性使用方式:1、作为普通函数,2、作为decorator
import {observable} form ‘mobx’ class Store{ @observable arr = []; @observable obj = {}; @observable mao = new Map(); @observable num = 1; @observable str = ‘str’; @observable bool = true; // 2. 作为decorator @computed get mixed(){ return store.str + ‘/‘+ store.num } } const store = new Store(); // 1. 作为普通函数 let foo = computed(function(){ return store.str + ‘/‘+ store.num }) // computed 接收一个方法,里面可以使用被观察的属性 // 监控数据变化的回调,当foo里面的被观察属性变化的时候 都会调用这个方法 foo.observe(function(change){ console.log(change) // 包含改变值foo改变前后的值 }) store.str = ‘1’; sotre.num = 2;
(2)、autorun:当我们使用decorator来使用computed,我们就无法得到改变前后的值了,这样我们就要使用autorun方法。从方法名可以看出是“自动运行”。所以我们要明确两点:自动运行什么,怎么触发自动运行自动运行传入autorun的参数,修改传入的autorun的参数修改的时候会触发自动运行
import {observable,autorun} form ‘mobx’ class Store{ @observable arr = []; @observable obj = {}; @observable mao = new Map(); @observable num = 1; @observable str = ‘str’; @observable bool = true; // 2. 作为decorator @computed get mixed(){ return store.str + ‘/‘+ store.num } } const store = new Store(); autorun(() => { console.log(store.str + ‘/‘+ store.num) }) store.str = ‘1’; sotre.num = 2;
(3)、when:用法: when(predicate: () => boolean, effect?: () => void, options?)
when 观察并运行给定的 predicate,直到返回true。 一旦返回 true,给定的
effect 就会被执行,然后 autorunner(自动运行程序) 会被清理。
该函数返回一个清理器以提前取消自动运行程序。
when方法接收两个参数(两个方法),第一个参数根据可观察属性的值做出判断
返回一个boolean值,当为true的时候,执行第二个参数。如果一开始就返回
一个true,就会立即执行后面的方法。
import {observable,when} form ‘mobx’ class Store{ @observable arr = []; @observable obj = {}; @observable mao = new Map(); @observable num = 1; @observable str = ‘str’; @observable bool = false; // 2. 作为decorator @computed get mixed(){ return store.str + ‘/‘+ store.num } } const store = new Store(); when(() => store.bool,()=> { console.log(‘it’s a true) }) store.bool = true;
(4)、reaction:用法:reaction(() => data, (data, reaction) => { sideEffect }, options?) 它接收两个函数参数,第一个(数据函数)是用来追踪并返回数据作为第二个函数(效果函数)的输入。不同于 autorun的是当创建时效果函数不会直接运行(第二个参数不会立即执行, autorun会立即执行传入的参数方法),只有在数据表达式首次返回一个新值后才会运行。在执行效果函数时访问的任何 observable 都不会被追踪。
import {observable,reaction} form ‘mobx’ class Store{ @observable arr = []; @observable obj = {}; @observable mao = new Map(); @observable num = 1; @observable str = ‘str’; @observable bool = false; // 2. 作为decorator @computed get mixed(){ return store.str + ‘/‘+ store.num } } const store = new Store(); reaction(() => [store.str,store.num],(arr) => console.log(arr.join(‘\’))) store.str = ‘1’; sotre.num = 2;
(5)、action: 在redux中,唯一可以更改state的途径便是dispatch一个action。这种
约束性带来的一个好处是可维护性。整个state只要改变必定是通过action触发的,对此
只要找到reducer中对应的action便能找到影响数据改变的原因。强约束性是好
的,但是Redux要达到约束性的目的,似乎要写许多样板代码,虽说有许多库都
在解决该问题,然而Mobx从根本上来说会更加优雅。 首先Mobx并不强制所有state的改变必须通过action来改变,这主要适用于一
些较小的项目。对于较大型的,需要多人合作的项目来说,可以使用Mobx提
供的api configure来强制。
(6)、observer:mobx-react的observer就将组件的render方法包装为autorun,所以当可观察属性的改变的时候,会执行render方法。
(7)、observable:observable是一种让数据的变化可以被观察的方法
observable(value) 是一个便捷的 API ,此 API 只有在它可以被制作成可观察的数据结构(数组、映射或observable 对象)时才会成功。对于所有其他值,不会执行转换。