共计 13615 个字符,预计需要花费 35 分钟才能阅读完成。
前言:
想零碎学习前端面试题,强烈推荐浏览 在线电子书(反对手机版,不断更新)。
本书特点:零碎全面(涵盖前端核心技术点),简洁,针对性强(针对面试场景设计)。
欢送在 github 上留言反馈
react 如何实现 keep-alive?
Keep-alive 是缓存路由应用的,保留之前路由的状态
实现办法:
-
应用 npm 库:
- react-router-cache-router
- React-activation
react 错误处理?
次要的 api(生命周期):
- componentDidCatch(error,errorInfo): 同样能够将谬误日志上报给服务器
- getDerivedStateFromError(error):更新 state 使下一次渲染可能显示降级后的 UI
注意事项:
- 仅可捕捉其子组件的谬误,无奈捕捉其本身的谬误
你有应用过 suspense 组件吗?
动静加载(异步组件)加载时会有提早,在提早期间能够将一些内容展现给用户,比方:loading
(react16.6 新增的 API)
const resource = fetchProfileData();
function ProfilePage() {
return (<Suspense fallback={<h1>Loading profile...</h1>}>
<ProfileDetails />
<Suspense fallback={<h1>Loading posts...</h1>}>
<ProfileTimeline />
</Suspense>
</Suspense>
);
}
function ProfileDetails() {
// 尝试读取用户信息,只管该数据可能尚未加载
const user = resource.user.read();
return <h1>{user.name}</h1>;
}
function ProfileTimeline() {
// 尝试读取博文信息,只管该局部数据可能尚未加载
const posts = resource.posts.read();
return (
<ul>
{posts.map(post => (<li key={post.id}>{post.text}</li>
))}
</ul>
);
}
参考资料:
何为 Suspense?
怎么动静导入组件,按需加载,代码宰割?
只有当组件被加载时,对应的资源才会导入
- react-loadable: npm 库 按需加载
- react.lazy: 原生反对(新版本 16.6),配合 suspense 一起应用,还要 webpack code splitting
- require(component) : 在特定条件下,动静引入
react Context 介绍?
次要 api:
- react.createContext : 创立 store
- [store].Provider: 包裹组件,并通过 value 字段传递参数
- [store].Consumer: 获取包裹组件内容
创立过程:
- 【创立 store】:通过 React.createContext 创立 AppContext 实例
- 【包裹整个组件】:应用 AppContext.Provider 组件
- 【注入全局变量】,在 AppContext.provider 组件上
- 【引入全局变量】:通过 AppContext.Consumer 组件,子组件的回调,获取 store 中的内容和办法
为什么 react 并不举荐咱们优先思考应用 context?
- 【实验性】context 目前还处于试验阶段,可能会在前期有大扭转,防止给将来降级带来麻烦
- 【稳定性】context 的更新须要通过 setState 触发,然而这并不是牢靠的。context 劫持跨组件拜访,然而,如果两头子组件通过一些办法不响应更新,比方 shouldComponentUpdate 返回 false,那么不能保障 context 的更新肯定达应用 context 的子组件。因而,context 的可靠性须要关注。不过是更新的问题,在新版的 APP 中得以解决
只有你能确保 context 是可控的,正当应用,能够给 react 组件开发带来弱小体验
render 函数中 return 如果没用应用 () 会用什么问题吗?
论断:如果换行就有问题
起因:babel 会将 jsx 语法编译成 js,同时会在每行主动增加分号(;), 如果 return 换行了,那么就变成了 return; 就会导致报错
// 这样会报错,react
class App extends React.Component{render(){
return
<div>111</div>
}
}
介绍下渲染属性 render props?
性能:给纯函数组件加上 state, 响应 react 的生命周期
长处:hoc的毛病 render prop 都能够解决
- 扩展性限度:hoc 无奈从内部拜访子组件的 state, 因而无奈通过 shouldComponentUpdate 过滤掉不必要的更新,react 在反对 es6 class 之后提供了 react.PureComponnet 来解决这个问题
- ref 传递问题:ref 被隔断,起初的 react.forwardRef 来解决这个问题
- Wrapper Hell(多层包裹):多层包裹,形象减少了复杂度和了解老本
- 命名抵触:屡次嵌套,容易笼罩老属性
- 不可见性:hoc 相当于黑盒
毛病:
- 应用繁琐:hoc 复用只需借助装璜器语法(decorator)一行代码进行复用,render props 无奈做到如此简略
- 嵌套过深:render props 尽管解脱了组件多层嵌套的问题,然而转化为了函数回调的嵌
参考资料:
React 中的 Render Props
React 如何进行组件 / 逻辑复用?
- HOC(高阶组件)
-
- 属性代理
- 反向继承
- 渲染属性(render props)
- react-hooks
- Mixin (已废除,不探讨)
PureComponent 组件介绍?
当 props/states 扭转时,PureComponent 会对它们进行浅比拟,起到性能优化的作用;
相当于在 component 组件的 shouldComponentUpdate 办法中进行了比拟才渲染
特地阐明:
- 援用对象的数据倡议不要应用 PureComponnet 组件,否则会有坑
JSX 实质是什么?
JSX 应用 js 的模式来写 html 代码
jsx 自身是语法糖,无奈间接被浏览器解析,须要通过 babel 或者 typescript 来转换成 js。
许多蕴含预配置的工具,例如:create- react app 和 next.js 在其外部也引入了 jsx 转换。
旧的 JSX 转换会把 jsx 转换为 React.createElement 调用。
jsx 调用 js 自身的个性来动态创建 UI,与于传统模式下的模板语法不同
react 中组件通信的几种形式?
react 组件之前通信次要要四种形式
- 父子组件:props,props 回调
- 兄弟组件:独特父级,再由父节点转发 props,props 回调
- 跨级组件:context 对象,注入全局变量:getChildContext; 获取全局变量:this.context.color;
- 非嵌套组件:应用 事件订阅,向事件对象增加监听器,和触发事件来实现组件之间的通信,通过引入 event 模块实现
- 全局状态管理工具:Redux,Mobox 保护全局 store
react UI 组件和容器组件的区别与利用?
容器组件:领有本人的状态,生命周期
UI 组件:只负责页面 UI 渲染,不具备任何逻辑,性能繁多,通常是无状态组件,没有本人的 state, 生命周期。
react 生命周期?
react 生命周期支流的次要有 2 个大的版本;
一个是 v16.3 之前的:
一个是 v16.3 之后的;
v16.3 之前 的生命周期次要分为 4 个阶段,8 个生命周期:
- 初始化值阶段 initialization:getDefaultProps,getInitialState;
- 初始阶段 mount:componentWillMount,componentDidMount;
- 更新阶段 update:componetWillReceiveProps ,shouldComponetUpdate ,componentWillUpdate,
- 销毁阶段 unmount:componetWillUnmount;
v16.3 之后的生命周期:
新引入了两个生命周期:
- getDerivedStateFromProps
- getSnapshotBeforeUpdate
提醒 3 个不平安的生命周期(在 v17 中要被删除)
- componentWillMount
- componentWillReceiveProps
- componetWillUpdate
新的命令周期:
React 的申请放在 componentWillMount 有什么问题?
错误观念:componentWillMount 中能够提前进行异步申请,防止白屏工夫;
剖析:componentWillMount 比 componentDidMount 相差不了多少微秒;
问题
- 在 SSR(服务端渲染)中,componentWillMount 生命周期会执行两次,导致多余申请
- 在 react16 进行 fiber 重写后,componentWillMount 可能在一次渲染中屡次调用
- react17 版本后要删除 componentWillMount 生命周期
目前官网举荐异步申请在 componentDidMount中
create-react-app 有什么长处和毛病?
长处:
疾速生成架手架
毛病:
- 默认不引入 polyfill, 须要在入口引入 babel-polyfill
- 默认只反对 css 热加载,不反对 html,js 热加载(举荐应用:react-hot-loader)
介绍下 Immutable?
Immutable 是一种不同变的数据类型,数据一旦被创立,就不能更改的数据,每当对它进行批改,就会返回新的 immutable 对象,在做对象比拟时,能晋升性能;
实现原理:
immutable 实现原理是长久化数据结构,构造共享,防止对数据对象进行深拷贝;
react、vue 有什么区别?
区别 | react | vue |
---|---|---|
模板引擎 | JSX,更多灵便,纯 js 语法(能够通过 babel 插件实现模板引擎) | vue template, 指令,更加简略(vue 也能够应用 jsx 语法) |
复用 | Mixin->Hoc->render props->hook | Mixin-> slot->Hoc(比拟用,模板套模板,奇怪做法)-> vue3.0 function baseed APi |
性能优化形式 | 手动优化:PureComponent/shouldComponentUpdate | 主动优化:准确监听数据变动 |
监听数据变动的实现原理 | 手动:通过比拟援用的形式(diff) | 主动:getter/setter 以及一些函数的劫持(当 state 特地多的时候,当 watcher 也会很多,导致卡顿) |
数据流 | 数据不可变,单向数据流,函数式编程思维 | 数据可变,双向数据绑定,(组件和 DOM 之间的),响应式设计 |
设计思维 | all in js (html->jsx, css->style-component/jss) | html,,css,js 写在一个文件中,应用各自的形式 |
性能内置 | 少(交给社区,reactDom,propType) | 多(使用方便) |
长处 | 大型项目更适合 | 兼容老我的项目,上手简略 |
数据流比照:
react 数据更改逻辑:
vue 数据更改逻辑:
参考资料:
Vue 和 React 的长处别离是什么?
集体了解 Vue 和 React 区别
Vue 与 React 的区别之我见
让 react 反对 vue 的 template 语法如何实现?
基于形象语法树 AST,实现解析模板指令的插件(应该是实现一个 babel 插件,因为 jsx 解析成 js 语法,是通过 babel 解析的)
对 react 的认识,它的优缺点?
长处:
- 提供了申明式的编程思维
- 提供了组件化的开发思维,大大提高前端开发的效率
- 引入了虚构 dom 的概念,使得 react 能够跨端进行类各界面开发,react native,react vr,ssr;
- 引入了 diff 算法,进步了渲染效率
有余:
- 侵入性强,对老代码只能重做,不能局部集成(比方 vue);
jsx 语法有什么特点相比 js?
jsx 以 js 为核心来写 html 代码
jsx 语法特点:
- 反对 js+html 混写;
- jsx 编译更快比 html
长处:jsx 类型平安的,在编译过程中就能发现错误;
create-react-app 如何实现,蕴含哪些内容,如何自定义一个脚手架?
定义:create-react-app 是一个疾速生成 react 我的项目的脚手架;
长处:
- 无需设置 webpack 配置
毛病:
- 暗藏了 webpack,babel presets 的设置,批改起来比拟麻烦
HOC
什么是高阶函数?
如果一个函数,承受一个或多个函数作为参数或者返回一个函数 ,就可称之为 高阶函数
特点:
- 是函数
- 参数是函数
- or 返回是函数
eg: array 对象中的 map,filter,sort 办法都是高阶函数
function add(x,y,f){return f(x)+f(y)
}
let num=add(2,-2,Math.abs)
console.log(num);
什么是高阶组件?
高阶组件就是一个函数(react 函数组件),接管一个组件,解决后返回的新组件
高阶组件是高阶函数的衍生
外围性能:实现形象和可重用性
它的函数签名能够用相似 hashell 的伪代码示意
- W(WrappedComponent)被包裹的组件,当传参数传入 hoc 函数中
- E(EnhancedComponent)返回的新组件
hocFactory:: W: React.Component => E: React.Component
高阶组件,不是真正意义上的组件,其实是一种模式;
能够对逻辑代码进行抽离,或者增加某个共用办法;
高阶组件是装璜器模式在 react 中的实现
主要用途:
- 代码重用,逻辑和疏导形象
- 渲染劫持
- 状态形象和管制
- Props 管制
参考资料:React 中的高阶组件及其利用场景
hoc 存在的问题?
一、静态方法失落
二、refs 属性不能透传
三、反向继承不能保障残缺的子组件树被解析
hoc 高阶组件应用场景?
react-redux:connect 就是一个高阶组件, 接管一个 component, 并返回一个新的 componet, 解决了监听 store 和后续的解决;
react-router:withrouter 为一个组件注入 history 对象;
你在我的项目中怎么应用的高阶组件?
不谈场景的技术都是在耍流氓
-
权限管制:// 也能够在 history 路由切换的时候,加个监听办法,在顶层做监听解决,不过页面会闪一下
- 页面级别:withAdminAuth(Page),withVIPAuth(Page)
- 页面元素级别:
- 组件渲染性能追踪
- 页面复用
- 全局常量(通过接口申请),能过 hoc 抽离 // 也能够通过全局状态治理来获取
- 对以后页面的一些事件的默认执行做阻止(比方:阻止 app 的默认下拉事件)
参考资料:
React 中的高阶组件及其利用场景
高阶组件和父组件的区别?
高阶组件能够重写传入组件的 state,function,props; 能够对代码逻辑进行抽离,重写;
父组件只是管制子组件的 view 层;
hook
hooks 原理剖析,如何实现?
参考:
[[译] 深刻 React Hook 零碎的原理](https://juejin.cn/post/684490…
hooks 与 react 生命周期的关系?
hooks 组件有生命周期,函数组件没有生命周期
hooks 的生命周期其实就是:
- useState
- useEffect
- useLayoutEffect
//hooks 模仿生命周期函数,与 class 的生命周期有什么区别
react hook 优缺点?
react hook 是 v16.8 的新个性;
传统的纯函数组件,
react hooks 设计目标,加强版的函数组件,齐全不应用‘类’,就能写出一个全功能的组件,不能蕴含状态,也不反对生命周期),hook 在无需批改组件构造的状况下复用状态逻辑;
劣势:
- 简洁:react hooks 解决了 hoc 和 render props 的嵌套问题,更加简洁(在不应用 class 的状况下,应用 state 及 react 其余个性(省的把纯函数组件 / 其余组件改来改去))
- 解耦:react hooks 能够更不便地把 UI 和状态拆散,做到更彻底的解耦
- 组合:hooks 中能够援用另外的 hooks 造成新的 hooks,组合变幻无穷
-
函数敌对:react hooks 为函数组件而生,解决了类组件的几大问题
- 解决了 this 的指向问题
- 让组件更好的复用(老的 class 组件简短、蕴含本身的状态 state)
- 让 react 编程格调更取向函数式编程格调,应用 function 代替 class
毛病(坑):
- 【useState 数组批改】应用 useState 批改 array 的值时,不要应用 push/pop/splice 等间接更改数据对象的办法,否则无奈批改,应该应用解构或其余变量代替
- 【hook 执行地位】不要在循环、条件、嵌套中调有 hook,必须始终在 react 函数顶层应用 Hook,这是因为 react 须要利用调用程序来正确更新相应的状态,以及调用相应的钩子函数,否则会导致调用程序不一致性,从而产生难以预料到的结果
- 响应式的 useEffect:当逻辑较简单时,可触发屡次
- 状态不同步:函数的运行是独立的,每个函数都有一份独立的作用域。函数的变量是保留在运行时的作用域外面,当咱们有异步操作的时候,常常会碰到异步回调的变量援用是之前的,也就是旧的(这里也能够了解成闭包场景可能援用到旧的 state、props 值),心愿输入最新内容的话,能够应用 useRef 来保留 state
- 毁坏了 pureComponent、react.memo 浅比拟的性能优化成果(为了取最新的 props 和 state, 每次 render 都要从新创立事件处函数)
- react.memo 并不能齐全代替 shouldComponentUpdate(因为拿不到 state change , 只针对 props change)
参考资料:
hooks 中的坑,以及为什么?
hooks 注意事项?
- 不同 hook 中,不要应用判断(if)
react hook 底层是基于链表(Array)实现,每次组件被 render 时,会按程序执行所有 hooks, 因为底层是链表,每个 hook 的 next 指向下一个 hook,所有不能在不同 hooks 调用中应用判断条件,因为 if 会导致程序不正确,从而导致报错
// 谬误示例
function App(){const [name,setName]=useState('xz');
// 这里不能应用 if 判断
if(configState){const [age,setAage]=useState('0')
}
}
react hooks 异步操作注意事项?
一、如何在组件加载时发动异步工作
二、如何在组件交互时发动异步工作
三、其余陷阱
参考资料:
React Hooks 异步操作踩坑记
react hooks API 有哪些?
hooks(实质是一类非凡的函数,能够为函数式注入一些非凡的性能)的次要 api:
根底 Hook:
- useState : 状态钩子,为函数组件提供外部状态
- useEffect:副作用钩子,提供了相似于 componentDidMount 等生命周期钩子的性能
- useContext:共享钩子,在组件之间共享状态,能够解决 react 逐层通过 props 传递数据;
额定的 Hook:
- useReducer: action 钩子,提供了状态治理,其基本原理是通过用户在页面上发动的 action,从而通过 reduce 办法来扭转 state,从而实现页面和状态的通信,应用很像 redux
- useCallBack:把内联回调函数及依赖项数组作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项扭转时才会更新
- useMemo:把 ”” 创立 ”” 函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项扭转时从新计算,能够作为性能优化的伎俩。
- useRef:获取组件的实例,返回一个可变的 ref 对象,返回的 ref 对象在组件的整个生命周期内放弃不变
- useLayoutEffect:它会在所有 DOM 变更后同步调用 effect
- useDebugValue
demo:
//useMemo
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
//useReducer
const [state, dispatch] = useReducer(reducer, initialArg, init);
参考资料:Hook API 索引
useEffect 介绍?
useEffect 能够让你在函数组件中执行副应用(数据获取,设置订阅,手动更改 React 组件中的 DOM)操作
默认状况下每次函数加载完,都会执行(不要在此批改 state,防止循环调用),useEffect 相当于是 class 组件中的 componentDidMount,componentDidUpdate,componentWillUnMount 三个函数的组合
参数阐明:
-
参数一:
- type:function
- 执行的函数
-
参数二(可选):监听值
- type:array
-
要监听的值(当监听值扭转才执行,如果只想执行一次能够传一个[]):如果值没有扭转,就不必执行 effect 函数,能够传入监听的值
-
return callBack: 清理函数,执行有两种状况
- componentWillUnmount
- 在每次 userEffect 执行前(第二次开始)
-
分类:
一)不须要革除
react 更新 DOM 之后运行的一些额定代码,操作实现即可疏忽
应用场景:
- 手动变更 DOM(批改 title)
- 记录日志
- 发送埋点申请
二)须要革除
effect 返回一个函数,在革除时调用(相当于 class 中 componentWillUnmount 生命周期)
因为增加 / 删除订阅代码的紧密性,所以 useEffect 设计在同一个中央,如果 effect 返回一个函数,react 将会在执行革除时调用它
应用场景:
- 订阅内部数据源(避免数据泄露)
- 设置页面题目,返回重置原题目
useEffect 和 useLayoutEffect 区别?
- useEffect 相比 componentDidMount/componentDidUpdate 不同之处在于,应用 useEffect 调度的 effect 不会阻塞浏览器更新屏幕,这让利用响应更快,大多数据状况下,effect 不须要同步地执行,个别情况下(例如测量布局),有独自的 useLayoutEffect hook 可应用,其 API 与 useEffect 雷同
- useEffect 在副应用完结之后,会提早一段时间执行,并非同步执行。遇到 dom 操作,最好应用 userLayoutEffect
- userLayoutEffect 外面的 callback 函数会在 DOM 更新实现后立刻执行,然而会在浏览器进行任何绘制前运行实现,阻塞了浏览器的绘制
useContext 介绍?
共享状态钩子,在组件之间共享状态,能够解决 react 逐层通过 props 传递数据的问题
应用流程(应用流程和 react-redux 差不多):
- 创立 store:通过 createContext Api
- 包裹整个组件:通过 store 中的 Provider 办法
- 注入全局变量,provider 组件中
- 引入全局变量:通过 useContext, 传入 store 的名字,返回一个 store 对象内容
const {useState, createContext, useContext} = React;
function App(){
// 创立 store
const AppContext=createContext({});
function A(){
// 从 store 中取值
const {name}=useContext(AppContext);
return <div>A 组件 Name:{name}</div>
}
function B(){
// 从 store 中取值
const {name}=useContext(AppContext);
return <div>B 组件 Name:{name}</div>
}
// 在顶层包裹所有元素,注入到每个子组件中
return (<AppContext.Provider value={{name:'xz'}}>
<A/>
<B/>
</AppContext.Provider>
)
}
ReactDOM.render(
<App />,
document.getElementById('app')
);
参考资料:
React Hooks 罕用钩子及基本原理
useReducer 介绍?
action 钩子,提供了状态治理
实现过程(和 redux 差不多,但无奈提供中间件等性能):
- 用户在页面上 发动 action(通过 dispath 办法)
- 从而通过 reducer 办法 来扭转 state, 从而实现 页面和状态的通信
如何创立本人的 hooks?
实现步骤:
- 定义一个 hook 函数,并返回一个数组(外部能够调用 react 其余 hooks)
- 从自定义的 hook 函数中取出对象的数据,做业务逻辑解决即可
useCallBack 介绍?
useState 介绍?
useState
是一个内置的 React Hook。useState(0)
返回一个元组,其中第一个参数 count
是计数器的以后状态,setCounter
提供更新计数器状态的办法。
...
const [count, setCounter] = useState(0);
const [moreStuff, setMoreStuff] = useState(...);
...
const setCount = () => {setCounter(count + 1);
setMoreStuff(...);
...
};
Fiber
什么是 Fiber?是为了解决什么问题?
react fiber 是一种基于浏览器的 单线程调度算法
react 算法的扭转(Fiber 实现的原理):
- 16 版本之前:reconcilation 算法实际上是递归,想要中断递归是很艰难的
- 16 版本之后:开始应用循环来代替之前的递归
fiber:一种将 recocilation(递归 diff),拆分成无数据个小工作的算法;它随时可能进行,复原。进行复原的机会取决于以后的一帧(16ms)内,还有没有足够的工夫容许计算
fiber 是 react16 中新公布的个性;
解决的问题:
react 在渲染过程时,从 setState 开始到渲染实现,两头过程是同步;
如果渲染的组件比拟大,js 执行会长工夫占有主线程,会导致页面响应度变差,使得 react 在动画,手势等利用中成果比拟差;
实现过程及原理(核心理念就是:time slicing):
- 拆分:把渲染过程进行拆分成多个小工作
- 查看:每次执行完一个小工作,就去对列中查看是否有新的响应须要解决
- 继续执行:如果有就执行优化及更高的响应事件,如果没有继续执行后续工作
refs
react 的 refs 有什么用,应用场景?
react 次要提供了一种规范数据流的形式来更新视图;
然而页面某些场景是脱离数据流的,这个时候就能够应用 refs;
react refs 是用来获组件援用的, 取后能够调用 dom 的办法;
应用场景
- 治理焦点、抉择文本或者媒体播放时,获取焦点 this,refs.inputPhone.focus();
- 触发式动画
- 与第三方 DOM 库整合
refs 注意事项:
不能在无状态组件中应用 refs
Virtual DOM
什么是 Virtual DOM,它的长处?
Virtual DOM 是对 DOM 的形象,实质是 js 对象,这个对象就是更加轻量级对 DOM 的形容
长处:
- 【性能优化】操作实在 DOM 慢,频繁变动 DOM 会造成浏览器回流 / 重绘,虚构 DOM 形象的这一层,在 patch(batching 批处理)过程中尽可能地一次性将差别更新到 DOM 中,升高更新 DOM 的频率
- 【数据驱动程序】应用数据驱动页面,而不是操作 DOM 的模式
- 【跨平台】:node 层没有 DOM, 然而 react 却能够在 node 层(SSR)运行
能够通过 chrome 的 console 面板中的
参考资料:
虚构 DOM 原理
Virtual DOM 的创立,更新,diff 过程?
虚构 DOM 的创立
虚构 DOM 是对实在 DOM 的形象,依据不同的需要,能够做出不同的形象,比拟 snabbdom.js 的形象形式
根本构造
/*
* 虚构 DOM 实质是一个 JS 对象,这个对象是更加轻量级的对 DOM 的形容
* */
//tagName,props,children
const element={
tagName:'ul',
props:{id:'list'},
children: [{
tagName:'li',
props:{class:'item'},
children:['item1'] //item1 只是没有包裹的子节点
}]
}
react diff 介绍?
传统的页面更新,是间接操作 dom 来实现的,比方原生 js 或者 jquery,然而这种形式性能开销比拟大;
react 在初始化的时候会生成一个虚构 dom, 每次更新视图会比拟前后虚构 dom 的区别;
这个比拟办法就是 diff 算法,diff 算法很早就曾经呈现了;然而 react 的 diff 算法有一个很大区别;
react diff 算法劣势:
传递 diff 算法:
- 遍历模式:循环递规 对节点进行顺次比照
- 工夫算法复杂度:o(n^3)次方,n 代表节点数
react diff 算法:
- 遍历模式:采纳 逐层比拟 的形式(DOM 的特点,个别很少呈现跨层级的 DOM 变更)
- 工夫算法复杂度:O(n)次方;
目前社区里的两个算法库:
- snabbdom.js(双端比拟算法):v2.0 借鉴
-
inferno.js(速度更快):vue3.0 借鉴
- 核心思想:利用 LIS(最长递增序列)做动静布局,找到最小的挪动次数
react 算法 PK inferno.js
-
react diff:
- 把 a,b,c 挪动到他们相应的地位
- 再 + 1 共三步操作
- inferno: 间接把 d 挪动到最后面,一步到位
A:[a,b,c,d]
B:[d,a,b,c]
同层比拟
参考资料:
diff 算法原理概述
setState
setState 之后产生了什么?
- 【数据合并】多个 setState 会进行数据合拼,筹备批量更新
- 【数据合并到组件的以后状态】生成新的 react tree
- 【更新 UI】比拟应用 diff 算法,比拟新旧 virtual dom,,最小化 DOM 操作
- 【执行回调函数】setState 第二个参数
setState 到底是同步还是异步?
论断:有时体现出同步,有时体现出“异步“
体现场景:
- 同步:setTimeout,原生事件;
- 异步:合成事件,钩子函数(生命周期);
react 异步阐明:
setState 异步并不是说外部代码由异步代码实现,其实自身执行过程和代码都是同步的,只是合成事件和钩子函数的调用程序在更新之前;在异步更新中,屡次 setState 前面的值会笼罩后面的;
为什么 setState 不设计成同步的?
- 放弃外部的一致性,和状态的安全性
放弃 state,props.refs 一致性;
- 性能优化
react 会对根据不同的调用源,给不同的 setState 调用调配不同的优先级;
调用源包含:事件处理、网络申请、动画;
- 更多可能性
异步获取数据后,对立渲染页面;放弃一致性,
react 事件
react 事件机制?
一、事件注册
- 【组件装载】装载 / 更新
- 【事件注册与卸载】能过 lastProps,nextProps 判断是否有新增、删除事件别离调用事件注册、卸载办法
- 【事件存储】能过 eventPluginHub, enqueuePutListener 进行事件存储
- 【获取 document 对象】
- 【事件冒泡 / 捕捉】依据事件名称(onClick,onCaptureClick)判断
- 【事件监听】:addEventListener,addachEvent(兼容 IE)
- 【注册原生事件】给 document 注册原生事件回调为 dispatchEvent (对立的事件散发机制)
二、事件存储
{
onClick:{fn1:()=>{}
fn2:()=>{}
},
onChange:{fn3:()=>{}
fn4:()=>{}
}
}
三、事件触发 / 执行
事件执行程序(原生事件与合成事件)
-
dom child
-
- dom parent
- react child
- react parent
- dom document
四、合成事件
- 【调用 EventPluginHub】的 extractEvents 办法
- 【遍历所有 EventPlugin】用来解决不同事的工具办法
- 【返回事件池】在每个 EventPlugin 中依据不同的事件类型返回
- 【取出合成事件】从事件池中取出,如为空,则创立
- 【取出回调函数】依据元素 nodeid(惟一标识 key) 和事件类型 从 listenerBink 中取出 回调函数
- 【返回合成事件】返回带有合成事件参数的回调函数
参考资料:
【React 深刻】React 事件机制
react 事件与原生事件的区别?
语法区别:
- 【事件名小驼峰】react 事件命令采纳小驼峰式,而不是纯小写
- 【事件办法函数】应用 JSX 语法时,你须要传入一个函数作为事件处理函数,而不是一个字符串
react 事件的长处
- 【兼容性更强】合成事件:react 事件对生成事件进行了包装,解决了浏览器兼容性问题(阻止浏览器默认行为,阻止冒泡)
react 事件与原生事件的执行程序?
- 原生事件,顺次冒泡执行
- react 合成事件,顺次冒泡执行
- document 事件执行
/*
* 执行后果:* 1. dom child
* 2. dom parent
* 3. react child
* 4. react parent
* 5. dom document
* */
react 事件与原生事件能够混用吗?
react 事件与原生事件最好不要混用
起因:
- 原生事件如果执行
stopProagation
办法,则会导致其余 react 事件生效,因为所有元素的事件将无奈冒泡到 document 上
react-router
React-Router 怎么设置重定向?
应用 重定向 Api : Redirect