-
react组件的生命周期
挂载阶段、更新阶段、卸载阶段 在`render()`方法中,根据组件的`props`和`state`返回一个React元素,用于描述组件的UI,真正渲染出页面DOM的工作由React自身负责。`render`是一个纯函数,在这个方法中不能执行任何有副作用的操作,不能去改变组件的状态。 `componentDidMount()`在组件被挂载到DOM之后调用,而且该方法只会被调用一次。这个时候已经可以获取到DOM结构,因此依赖DOM节点的操作可以放到该方法中。此外,这个方法通常还会用于向服务器端请求数据,在这个方法中可以调用`this.setState()`,调用`this.setState()`会引起组件的重新渲染。。 `componentDidUpdate`在组件更新之后被调用,可以作为操作更新后的DOM的地方组件被挂载到DOM后,`props`或`state`都可以引起组件的更新。 - `componentWillUnmount`在组件被卸载前调用,可以在这里执行一些清理工作,比如清除组件中使用的定时器,清除`componentDidMount`中手动创建的DOM元素等,以避免引起内存泄露。 -
什么是jsx
JSX是一种JavaScript的语法扩展,JSX会被babel编译为:React.createElement(), React.createElement()将返回一个叫作“ReactElement”的JS对象。可以在 `if` 语句和 `for` 循环的代码块中使用 JSX,将 JSX 赋值给变量,把 JSX 当作参数传入,以及从函数中返回 JSX -
常见hook的使用
usestate `useState()` 方法里面唯一的参数就是初始 state hook规则,只在最顶层使用 Hook,不要在循环,条件或嵌套函数中调用 Hook,### 只在 React 函数中调用 Hook useeffect 你可以告诉 React 组件需要在渲染后执行某些操作。React 会保存你传递的函数 默认情况下,它在第一次渲染之后*和*每次更新之后都会执行。 useMemo 在父组件给子组件传递参数时,如果父组件的对象属性发生变化,那么子组件也会重新渲染,useMemo可以在父组件传递的参数没有发生变化时,不会重新渲染子组件,传入两个参数,- 第一个参数是个函数,返回的对象指向同一个引用,不会创建新对象;- 第二个参数是个数组,只有数组中的变量改变时,第一个参数的函数才会返回一个新的对象。 useCallback 父组件state变化,重新渲染,会重新创建方法函数,传给子组件的方法属性发生变化,导致子组件渲染 useContext 处理层级较深的组件间传递,在组件外部createContext,使用Context.Provider提供一个context对象,在子组件中使用useContext可以获取到祖组件的值。 -
render方法触发的条件
父组件传递给子组件值props 父组件state发生变化 组件state发生变化 -
react的合成事件系统
通过 JSX 方式绑定的事件,比如 onClick={() => this.handle()},基于浏览器的事件机制实现的,通过冒泡事件冒泡到顶层元素,再统一分发处理 -
什么是高阶组件hoc
用于复用组件逻辑,高阶组件是函数,它接受一个组件作为参数,然后返回一个新的组件,一种设计模式,类似于装饰器模式 -
key的作用
在render函数执行的时候,新旧两个虚拟DOM会进行对比,如果两个元素有不同的key,那么在前后两次渲染中就会被认为是不同的元素,这时候旧的那个元素会被销毁,新的元素会被创建。如果提供了唯一的标识key且是相同的key,且元素类型相同, 若元素属性有所变化,则React只更新组件对应的属性,这种情况下,性能开销会相对较小。 -
context的用法与使用场景
-
错误边界(Error Boundaries)用法与使用场景
页面由于某个 `React` 组件渲染错误(代码书写错误不规范或后端接口字段调整出错),导致整个应用被挂载出现白屏,且可能无法追踪造成影响极大,**任何未被错误边界捕获的错误将会导致整个 React 组件树被卸载**`Error Boundaries` 是一种 React 组件,这种组件**可以捕获并打印发生在其子组件树任何位置的 JavaScript 错误,且会渲染出兜底 UI**。
1.2.2. redux
-
为什么要使用redux,解决了什么痛点
redux解决的是react组件之间通信以及项目的状态变量的保存问题。如果不使用redux,随着项目的越来越大,组件之间通信越来越复杂,组件的状态越来越多,项目将越来越难以维护。使用redux之后,项目的状态都保存到store之中,各个组件可以直接从store之中获取到自己需要的状态,如果需要改变store中的状态,redux也提供了dispatch方法,组件可以dispatch一个action,根据action的type属性,reducer会对状态做出变化。 -
阐述redux三大原则
单一数据源,整个应用的 被储存在唯一的一个store中 State 是只读的:唯一改变 state 的方法就是触发 [action],action 是一个用于描述已发生事件的普通对象。 使用纯函数来执行修改。Reducer 只是一些纯函数,它接收先前的 state 和 action,并返回新的 state -
阐述redux数据流过程
严格的单向数据流,调用[`store.dispatch(action)`],Redux store 调用传入的 reducer 函数 [Store] 会把两个参数传入 [reducer]: 当前的 state 树和 action。**根 reducer 应该把多个 子 reducer 输出合并成一个单一的 state 树****Redux store 保存了根 reducer 返回的完整 state 树。** -
如果注册了两个一模一样的reducer,会产生什么问题
state变量,是从方法的参数中传递过来的,意味着在第一个reducer执行完后的变化还没有对这个state产生影响,在第二个reducer执行的时候还是原来state的值。 -
阐述redux的middleware,其目的是什么
如果没有中间件的运用,redux 的工作流程是这样 action -> reducer,这是相当于同步操作,由dispatch 触发action后,直接去reducer执行相应的动作。有了中间件,redux 的工作流程就变成这样 action -> middlewares -> reducer,点击按钮就相当于dispatch 触发action,接下去获取服务器数据 middlewares 的执行,当 middlewares 成功获取到服务器就去触发reducer对应的动作,更新需要渲染视图的数据 -
阐述combineReducers作用及其原理
随着应用变得越来越复杂,可以考虑将 [reducer 函数] 拆分成多个单独的函数,拆分后的每个函数负责独立管理 [state]的一部分。 合并后的 reducer 可以调用各个子 reducer,并把它们返回的结果合并成一个 state 对象。
1.2.3. dva
-
什么是dva,解决了什么痛点dva
首先是一个基于 redux和 redux-saga的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router和 fetch,所以也可以理解为一个轻量级的应用框架。 -
阐述Model对象的基本组成及其作用
这个模块我理解的是主要用来处理数据,就是所谓的数据层,model主要包含五个部分 namespace:命名空间 state:数据的初始化,优先级低于 dva() 的 opts.initialState reducers:同步更新state,唯一可以更改state的地方,通过action触发 effects:异步更新state,不直接修改state,通过action触发 subscriptions:订阅数据源(数据源可以是当前的时间,服务器的 websocket连接, keyboard输入,geolocation变化,history路由变化等等),然后根据需要 dispatch相应的 action -
@umijs/plugin-dva的启用条件是什么
配置开启`immer`,**约定式的 model 组织方式**,**文件名即 namespace** -
dva-loading的实现原理
可以自动处理 loading 状态,不用一遍遍地写 showLoading 和 hideLoading
1.2.4. redux-saga
-
redux-saga是什么,解决了什么痛点?
主要是为了更优雅地 管理 Redux 应用程序中的 副作用,映射在 Javascript 程序中,它的目标是让副作用管理更容易,执行更高效,测试更简单,在处理故障时更容易。 -
什么是saga
-
什么是Effect
Side Effects 主要指的就是:异步网络请求、本地读取 localStorage/Cookie 等外界操作 -
执行dispatch(action)时,redux-saga经历了什么过程
middleware 我们需要发起一些 action,然后让 middleware 执行真实的 dispatch
1.2.5. react-redux
-
阐述react-redux的作用
作用1将组件分为了容器组件和UI组件,UI组件通过props来获取状态和操作状态的方法。 作用2通过Provider组件来取代redux中的store.subscribe来监听组件的状态变化,用于渲染组件。 作用3在容器组件中通过核心API connect来连接UI组件和redux,connect是一个高阶函数,第一个参数接收的是两个回调函数, 回调函数1:将接收一个state,然后返回一个对象对象中包含了UI组件想要的状态。 回调函数2:接收一个dispatch,返回一个对象,对象中包含了UI组件想要操作状态的方法。同时还有一个简写方法,就是第二个参数直接传入一个对象,该对象包含操作状态的方法。(核心:就是将state和dispatch映射到UI组件的props中) -
阐述Provider,connect,useSelector相关API的用法
useSelector相关API的用法 从redux的store对象中提取数据 connect方法,用于从 UI 组件生成容器组件。connect的意思,就是将这两种组件连起来。connect方法接受两个参数:mapStateToProps和mapDispatchToProps。它们定义了 UI 组件的业务逻辑。前者负责输入逻辑,即将state映射到 UI 组件的参数(props),后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action。 Provider在根组件外面包了一层,这样一来,App的所有子组件就默认都可以拿到state了。 -
阐述store变化到组件更新的整个流程
UI组件会先通过useDIspatch或者connect的mapDispatchToProps分发action,通过reducer纯函数去修改store的state,state发生变化后,通过UI组件的props会引起组件的更新。 -
如何避免store变化时无关组件频繁渲染
通过useMemo去监听数据的变化
1.2.6. react-router
-
阐述hashHistory与browserRouter的区别
BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。HashRouter使用的是URL的哈希值。 BrowserRouter的路径中没有#1. 刷新后对路由state参数的影响BrowserRouter没有任何影响,因为state保存在history对象中。HashRouter刷新后会导致路由state参数的丢失!!! -
阐述Router、Route相关API的用法
Router有BrowserRouter、HashRouter、MemoryHistory Route只是一个具有渲染方法的普通 React 组件,路由匹配成功则渲染该组件。 path:路由的匹配规则(可以省略) exact:用于精确匹配路由(可以省略) component:需要渲染的组件 顶层的 Router 组件负责分析监听 URL 的变化,在它之下的 Route 组件可以直接读取这些信息。Router 是“提供者”,Route是“消费者” -
如何渲染多层级路由
嵌套路由children -
阐述路由变化到组件更新的整个过程
当我们点击Link组件的时候,修改了浏览器地址栏中的url React路由监听地址栏url的变化 React路由内部遍历所有的Route组件,拿着Route里面path规则与pathname进行匹配 -
阐述history的底层机制
用户访问网页的历史记录通常会被保存在一个类似于栈中,即history对象,点击返回就出栈,跳下一页就入栈。 它提供了方法操作页面的前进和后退: - window.history.back() 返回到上一个页面 - window.history.forward() 进入到下一个页面 - window.history.go([delta]) 跳转到指定页面
1.2.7. umi
-
阐述对umi框架的认识
Umi 以路由为基础的,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展,Umi 实现了完整的生命周期,并使其插件化,Umi 内部功能也全由插件完成 -
项目中用到了哪些umi plugin,分别是什么作用
plugin-antd plugin-dva plugin-layout -
从执行umi dev到页面启动,umi做了啥
启动在浏览器中运行的开发服务器,并监视源文件变化,自动热加载。 -
分析.umi目录到组成与作用
.umi 临时目录是整个 Umi 项目的发动机,你的入口文件、路由等等都在这里,这些是由 umi 内部插件及三方插件生成的 ```+ .umi+ core # 内部插件生成 + pluginA # 外部插件生成 + presetB # 外部插件生成 + umi.ts # 入口文件
- 如何注册、使用一个umi plugin
Plugin.register
Plugin.applyPlugins