一. react 相关知识点
1. react中setState后发生了什么
-
在代码中调用setState函数之后,React会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation) 。
-
经过调和过程,React 会以相对高效的方式根据新的状态构建React元素树并且着手重新渲染整个UI界面。
-
在React得到元素树之后,React会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染。在差异计算算法中,React 能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染
2. react 的 setState 是同步还是异步
测试:在componentDidMount的setTimeout方法里调用setState是同步的;在componentDidMount中直接调用setState是异步的;在dom中绑定onClick(React的合成函数:抹平不同浏览器和端的差异)直接调用setState也是异步的。
源码分析
1、setState入口函数: 在setState函数中调用enqueueSetState, 拿到内部组件实例, 然后把要更新的partial state存到其_pendingStateQueue中,至此,setState调用方法执行结束,接下来是setState调用之后的动作。
2、调用 setState 后发生了什么: setState调用之后执行方法enqueueUpdate isBatchingUpdates === true分支,没有执行更新操作; setTimeout走的是isBatchingUpdates === false分支,执行更新;
3、isBatchingUpdates是事务batchingStrategy的一个标记,如果为true,把当前调用setState的组件放入dirtyComponents数组中,做存储处理,不会立即更新,如果为false,将enqueueUpdate作为参数传入batchedUpdates方法中,在batchedUpdates中执行更新操作。
3. React实现缓存的方式有哪些?他们有什么区别?
- React 组件中常用 PureComponent、React.memo、hook函数useCallback、useMemo等方法 缓存上次计算的结果。
2.PureComponent:主要是用在类组件中,使用PureComponent, 每次会对props进行一次浅比较,也可以在shouldComponentUpdate,去做更深层次的比对。
-
React.memo、hook函数useCallback、useMemo主要应用在函数组件中。
-
React.memo :相比于 PureComponent 可以支持指定一个参数,可以相当于shouldComponentUpdate的作用,因此 React.memo() 相对于 PureComponent 来说,用法更加方便。React.memo 一般用在「计算派生状态的代码」非常耗时的场景中,如:遍历大列表做统计信息
-
useCallback、useMemo 可以进行细粒度性能优化, 他们都可以缓存函数的引用或值,但是从更细的使用角度来说 useCallback 缓存函数的引用,useMemo 缓存计算数据的值。
4. React 组件中怎么做事件代理?它的原理是什么?
-
React基于Virtual DOM实现了一个SyntheticEvent层(合成事件层),定义的事件处理器会接收到一个合成事件对象的实例,它符合W3C标准,且与原生的浏览器事件拥有同样的接口,支持冒泡机制,所有的事件都自动绑定在最外层上。在React底层,主要对合成事件做了两件事:
-
事件委派: React会把所有的事件绑定到结构的最外层,使用统一的事件监听器,这个事件监听器上维持了一个映射来保存所有组件内部事件监听和处理函数。
-
自动绑定: React组件中,每个方法的上下文都会指向该组件的实例,即自动绑定this为当前组件。
5. 对React-Fiber的理解,它解决了什么问题?
-
React V15 在渲染时,会递归比对 VirtualDOM 树,找出需要变动的节点,然后同步更新它们, 一气呵成。这个过程期间, React 会占据浏览器资源,这会导致用户触发的事件得不到响应,并且会导致掉帧,导致用户感觉到卡顿。
-
为了给用户制造一种应用很快的“假象”,不能让一个任务长期霸占着资源。 可以将浏览器的渲染、布局、绘制、资源加载(例如 HTML 解析)、事件响应、脚本执行视作操作系统的“进程”,需要通过某些调度策略合理地分配 CPU 资源,从而提高浏览器的用户响应速率, 同时兼顾任务执行效率。
-
所以 React 通过Fiber 架构,让这个执行过程变成可被中断。“适时”地让出 CPU 执行权,除了可以让浏览器及时地响应用户的交互,还有其他好处:
-
分批延时对DOM进行操作,避免一次性操作大量 DOM 节点,可以得到更好的用户体验;
-
给浏览器一点喘息的机会,它会对代码进行编译优化(JIT)及进行热代码优化,或者对 reflow 进行修正。
核心思想: Fiber 也称协程或者纤程。它和线程并不一样,协程本身是没有并发或者并行能力的(需要配合线程),它只是一种控制流程的让出机制。让出 CPU 的执行权,让 CPU 能在这段时间执行其他的操作。渲染的过程可以被中断,可以将控制权交回浏览器,让位给高优先级的任务,浏览器空闲后再恢复渲染。
6、在React中怎么使用async/await?
-
从7.6.0版本往后,Node就开始全面支持async/await语法了。async/await 能让你的代码更整洁和可读。
-
用的最多的地方就是用来获取网络数据和初始化一些数据的生命周期函数componentDidMount里,这里是一个绝佳的位置使用async/await. 语法很方便,你会想要在你的React组件内使用的。 create-react-app 支持开箱即用的async/await.
-
但是如果你是用自己配制的webpack模板,你会遇到regeneratorRuntime is not defined异常。 解决这个异常的的关键是?babel-preset-env 和一些简单的配置。
-
npm i babel-preset-env --save-dev打开.babelrc文件,做如下内容更新:
{
"presets": [
["env", {
"targets": {
"browsers": [
">0.25%",
"not ie 11",
"not op_mini all"
]
}
}], "react"
]
}
- 从此你就只可以在React世界中放飞async/await了。
7. redux和mobx
1.编程范式不同 : redux:函数式编程 函数是一等公民 使用函数表达式 不可变数据 纯函数, 函数组合,高阶函数,函数柯理化等都是函数式编程中的概念。 mobx: 面向对象
2.内存开销 redux: 不可变数据 需要用到拷贝去生成新的对象 支持数据回溯 内存开销大 mobx: 状态可变 mobx始终使用一份引用 内存开销较小
3.应用性能 mobx:性能好 当我们访问某个属性的时候 有一个收集依赖的过程, 一旦值发生变化mobx可以精确观察更新每一个状态,然后再去渲染对应的组件 redux: 派发动作 通过纯函数reducer修改数据 全局状态变更 通过高阶函数Provider和connent进行数据分发 将状态映射为每个组件的属性
-
mobx是一个简单可扩展的状态管理库
-
相同的地方是都是单向数据流。
-
不同的地方是 redux 是函数式思想的实现,通过 reducer 函数管理状态,一般会用 immutable 的库来提高创建新对象的性能。而 mobx 是面向对象的思想,通过响应式代理来管理状态,可以通过 class 组织 state。
-
性能方面 mobx 的响应式能精准的通知依赖做更新,而 redux 只能全局通知,而且 mobx 只是修改同一个对象,不是每次创建新对象,性能会比 redux 更高。
-
然后我们又通过一个 demo 来入门了下 react 中使用 mobx:通过 class 组织状态,然后创建响应式代理,组件用 observer 高阶组件做一层包装,传入 mobx 的对象,这样 mobx 和组件就结合到了一起,状态更新就能通知到组件。
-
之后我们从源码层面理清了 mobx 的响应式机制的实现原理:mobx 会在对象上添加一个 Symbol($mobx) 的隐藏属性,用来放 ObservableObjectAdministration 对象,它是用于管理属性和它的依赖的,在 get 的 时候收集依赖,然后 set 的时候就可以通知所有收集到的依赖(Reaction)做更新。
8. JSX是什么
- 实际上,JSX仅仅只是 React.createElement(...) 函数的语法糖, 是JavaScript 语法的扩展,它允许编写类似于 HTML 的代码
9. react 生命周期
- state 是初始化状态,props是参数(只读)
- 主要分为三个阶段:
- 组件挂载:mounting
- constructor:初始化 state 和绑定方法
- getDerivedStateFromProps:静态方法,render之前调用,第一个参数是下一个props,第二个参数是上一个state,(替代componentWillReceiveProps),主要作用是监听props,然后修改当前组件的 state
- componentWillMount:会在render之前调用,组件将要挂载
- render:获取最新的state
- componentDidMount:组件render挂载后调用,适合发起网络请求
- 组件更新:receive_props
- componentWillReceiveProps -> (16.3之后版本使用:getDerivedStateFromProps):组件接收到新的props时调用,用于父组件更新状态时子组件的重新渲染
- shouldComponetUpdate:组件是否更新,适合处理副作用,返回true表示需要更新,false不需要更新
- componentWillUpdate:会在render之前调用,组件将要更新
- render:获取最新的state
- getSnapshotBeforeUpdate:在 render 之后 DOM 变更之前被调用,第一个参数是更新前的props(prevProps),第二个参数是更新前的state(prevState),return snapshot 此返回值将作为 componentDidUpdate 的第三个参数进行接收,使用场景:更新后恢复滚动位置
- componentDidUpdate:组件 更新后调用,第三个参数是snapshot
- 组件卸载:unmounting
- componentWillUnmount:组件卸载前调用,适合清理资源
10. react-router-dom
-
history 路由模式:
- BrowserRouter:使用HTML5 History API 来管理路由,不会在URL中出现hash值 /
- switch:
Switch用于管理多个路由的组件,它会按顺序匹配路径,并渲染第一个匹配的Route。这在处理多个路由时非常有用,特别是当多个路径可能匹配同一个 URL 时
-
hash 路由模式:
- hashRouter:使用URL中的hash值进行路由管理 #
-
generatePath:可以根据路径模板和参数生成一个完整的 URL 路径,接受2个参数
- path:路径模板,可以包含动态部分,例如 '/user/:id'
- params:一个对象,包含路径模板中使用的参数键值对,const userPath = generatePath('/user/:id', { id: 123 }); -> /user/123
- withRouter 是 React-Router 提供的一个高阶组件(HOC)。在React应用中,它用于将 match、location 和 history 对象注入到一个已有的组件中,这样组件就可以访问到当前路由的信息。在使用reactRouter的情况下,在一个非路由组件中获取路由参数或者控制路由跳转,可以通过withRouter高阶组件来实现 (包裹上之后,可以获取到history身上的api -> export default withRouter(Header))
- 在React Router v6中,withRouter已经被移除,取而代之的是使用 useNavigate、useLocation和useParams 钩子
- exact 为true开启严格匹配,/home/a
- Redirect 匹配不到的时候,重定向到某个页面
- params路由参数:获取 this.props.match.params
- search路由参数(to="xx?a=10&b=20":荻取到的search是urlencoded编码字符串,需要信助querystring解析,qs from 'querystring' 库, 获取 qs.parse(this.props.location.search)
- state路由参数(to={{pathname:"/home",state:{a:10,b:20}}}):获取 this.props.location.state,虽然地址栏没有参数,但刷新也可以保留住参数,因为使用BrowserRouter路由的history,不清缓存的情况就会记录下来
- history路由实例方法:事件处理,可以调用history的方法用户跳转页面和添加参数,this.props.history
-
BrowserRouter与HashRouter的区别
- 1.底层原理不一样:BrowserRouter使用的是H5history API. 不兼容IE9及以下版本. HashRouter使 用的是URL的哈希值.
- 2.path表现形式不一样:BrowserRouter的路径中没有#,例如:localhost:3000/demo/test hashReouter的路径包含#,例如:1ocalhost:3000/#/demo/test
- 3.刷新后对路由state参数的影响:
- (1).BrowserRouter没有任何影响,因为state保存在history对象中.
- (2).HashRouter刷新后会导致路由state参数的丢失!!!
- 4.备注:HashRouter可以用于解决一些路径上的相关问题
11. Redux
- Redux 核心概念:
- 当应用中的某些事件发生时(例如用户点击按钮),会 dispatch 一个 action。这个 action 被发送到 store,store 会调用 reducers。每个 reducer 对自己的数据负责,处理 action 并返回新的状态。最后,新的状态被保存到 store 中,UI组件可以通过订阅 store 的变化来更新自己
- Redux 的中间件它允许你在 action 发出之后但在到达 reducer 之前,对 action 进行处理。中间件可以用来处理异步操作、记录日志、路由管理等多种任务
- actions:描述发生了什么变化的普通的JavaScript,例如:用户点击按钮、数据加载完成等
- reducers:根据 actions 产生新的状态,reducers 接受先前的状态和一个 action,返回新的状态对象
- store:redux 应用中保存着整个应用的状态,每个 redux 应用只有一个 store,但可以有多个 reducers来管理不同的状态切片
- applyMiddleware: Redux的API之一,用于安装中间件,中间件可以让你在action被dispatch到store之前拦截并处理它们,或者在action到达reducer前产生新的action const store = createStore(reducer, applyMiddleware(thunk, loggerMiddleware));
- redux-thunk: 一个流行的Redux中间件,允许你编写可返回函数的action creators,这种特殊的action可以在 dispatch时一步调用其他action,从而简化了一步操作的处理
- React 和 Redux 的集成在最新版本中变得更加简洁和高效
- Store 是 Redux 的核心,它保存应用的全部状态,通过 createStore 创建函数,可以传入一个 reducer 函数来管理状态的变化, 使用 combineReducers 函数将多个 reducer 组成一个根 reducer
- 在入口文件中创建 React 应用,并使用 Provider 组件将 store 传递给整个应用。
- 所有的后代都可以使用 useSelector 和 useDispatch 都可以访问 store
- useSelector 用于从 store 中选择和读取数据
- useDispatch 用于获取 dispatch 函数,用于发送 action 到 store
- react-redux的connect 函数接收两个参数:mapStateToProps和mapDispatchToProps。前者负责将Redux store的state映射为React组件的props,后者则将action creators转换为可以直接调用并自动dispatch的props方法。经过connect处理后的组件,在渲染时会根据store的状态变化而重新渲染,并且可以直接通过props来触发Redux actions。
- content的概念和作用:content 是一个用来连接 React 和 Redux state 的函数,他的作用是将 Redux 的state 和 dispatch 映射到 React 组件的 props 上,从而让 React 组件可以访问到 Redux 的数据和操作 Redux 的 action. 这样的设计能够让 React 组件直接访问全局的state, 而不需要通过 props 层层传递,这种当时可以简化组件的数据流,提高数据的访问效率。通过这种方式,React 组件就不需要在 React 组件内部再引入 Redux 相关代码,可以减少组件和 Redux 只见的耦合度,提高组件的复用性。
12. hooks 相关概念
- useEffect 是 React 中的一个 Hook,用于在函数组件中处理副作用(如数据获取、订阅、手动更改 DOM 等)。与类组件中的生命周期方法(如 componentDidMount、componentDidUpdate 和 componentWillUnmount)类似,useEffect 让你在函数组件中完成相同的操作:
- 如果依赖数组为空,副作用函数只会在组件挂载和组件卸载时执行一次,类似于 componentDidMount 和 componentWillUnmount。
- 如果不传依赖数组,副作用会在每次组件渲染后执行,类似于 componentDidUpdate。
- 如果依赖数组有值,则组件会在挂载时运行一次,当标识副作用依赖的变量发生变化,副作用函数会重新执行;需要注意的是,useEffect的依赖项数组中的值必须是引用类型或基本类型,不能是函数。如果依赖项是函数,可以使用useCallback或useMemo来包装函数,以确保依赖项的引用不会发生变化。
- useState :管理状态,让开发者能够在函数组件里面拥有state并通过seTxx来修改state
- useContent:访问上下文,用于共享那些通用组件树传递的值,创建 React.createContext(themes), 获取const useContext(theme)
- useReducer:管理复杂的state的状态逻辑
- useCallback:记忆函数,依赖的变量发生变化才会执行函数,性能优化
- useMemo:记忆计算结果,依赖的变量发生变化,才会重新计算结果;缓存子组件,react默认会更新所有子组件,通过memo可以按需更新子组件
- useRef:创建可变引用对象,获取dom节点
- useLayoutEffect:在DOM更新后同步执行
- createRef 是一个函数,在类组件中使用,用于创建ref容器, 只能存一个, 用于访问到实际的dom元素,xx.current.value
- 在类组件中,使用 React.createRef() 创建一个引用对象;在函数组件中使用 useRef(null) 创建一个引用对象
- forwardRef 是一个函数,用于对 ref 进行转发和传递,使得父组件可以获取子组件的引用,用于在高阶组件(HOC)中传递ref, 因为默认情况下,ref 不能被传递,但用此函数包裹后就能使得 ref 被传递到子组件上
- useRef 是 react 的一个 Hook,用于在函数组件内创建ref, 不仅可以用它来引用 DOM 元素或者组件实例,也可以用来在整个组件生命周期内存储和操作可变值。使用useRef 创建的ref 在整个组件生命周期内保持不变
13. 类组件和函数组件之间的区别
- 类组件可以使用其他特性,如状态和生命周期钩子,并且他有this
- 函数组件只能接收props渲染到页面,无状态组件,没有this,不能使用生命周期钩子
- 函数组件性能要高于类组件,因为类组件使用要实例化,而函数组件直接执行取返回结果即可,为了提高性能,尽量使用函数组件
14. react 的 state 和 props 区别
- . 相同点:都是普通的js对象,他们包含着影响渲染输出的信息
- . 不同点:state 是组件自己管理数据,控制自己的状态,可变;props 是外部传入的数据参数,不可变
- . 没有state的叫做无状态组件,有state的叫有状态组件。
- . 多用props,少用state
二. vue 相关知识点
1. vue2
1.vue-router 路由生命周期也叫导航守卫
1. 全局守卫
1. beforeEach 全局前置守卫
2. beforeResolve 全局解析守卫
3. berEach 全局后置守卫、钩子
2. 组件内守卫
1. beforeRouteEnter 路由跳转触发,使用此组件,拿不到this
2. beforeRouteUpdate 组件复用时候触发,可以拿到this
3. beforeRouteleave 路由跳转触发,不使用此组件,可以拿到this
3. 路由独享守卫
1.beforeEnter 加载到页面之前做的事情
2. vue3
1.vue3 proxy响应式数据原理是
- Object.defineProperty无法监控到数组下标的变化,导致通过数组下标添加的元素,不能实时响应
- Object.defineProperty 只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。proxy 可以劫持整个对象,并返回一个新的对象
- proxy 不仅可以代理对象,还可以代理数组,还可以代理动态增加的属性
- proxy有多达13种拦截方法
- proxy作为新标准将收到浏览器厂商重点持续的性能优化
- proxy只会代理对象的第一层,通过判断当前reflect.get的返回值是否为object,如果是则在通过reactive方法做代理,这样就实现了深度观测
- 监听数组的时候可能触发多次get/set,如何防止多次触发,判断key是否为当前被代理对象target自身属性,也可以判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行trigger
2. vue2 与 vue3 diff算法
- vue2的核心diff算法采用了双端比较的算法,同时从新旧children 的两端开始进行比较,借助 key 值找到可复用的节点,在进行相关操作,相比react的diff算法,同样情况下可以减少移动节点次数,减少不必要的性能损耗,更加的优雅。
- vue3借鉴了ivi 算法 和 inferno 算法,在创建VNode 时就确定其类型,以及在 mount/patch 的过程汇总采用位运算来判断一个 VNode 的类型,在这个基础之上在配合核心的diff算法,使得性能上较vue2有了提升,该算法中还运用了动态规划的思想求解最长递归子序列。
3.vue3重大变革
1. 更小的体积包:vue3中,完全重写响应式系统,使其变的更加高效且API更简洁明了。配合 Tree shaking 和懒加载技术,vue3包的大小相比vue2大幅度提降低
2. 更灵活的组件注册方式:可以通过defineComponent 函数定义组件, 并使用setup 函数来代替vue2中的data\methods等选项。这样使得组件更容易测试和服用,并提高了开发效率
3. 改进的虚拟DOM算法:vue3改进了虚拟DOM算法,使之更加高效。其中,采用了模版编译为静态渲染函数的方式,这种方式具有更高的执行效率和更少的内存占用
4. 优化的响应式系统:vue3中的响应式系统,重构了内部细节和API,并采用了proxy对象代替Object.defineProperty实现响应式,这种方式使得响应式系统性能更好,并允许监听更多类型的属性
4.vue3新特性
vue3是vue.js框架的最新版本,带来了一系列令人期待的新特性,包括响应式API,composition API 和 Teleport等,从而提高应用程序的性能和可维护性
响应式API: 采用了proxy 代理对象来实现数据响应式。当数据发生变化时,proxy会自动触发更新操作,从而实现数据的响应式更新。相比 vue2的 Object.defineProperty 方法,Proxy 具有更高的性能和更好的兼容性。vue3的响应式API具有更高的性能和更好的兼容性,能更好的支持大规模数据和复杂组件
Composition API 是一种新的组件API,它将组件的逻辑代码按照功能进行划分,从而使得组件的代码更加清晰和可维护
Tepleport 指定该组件渲染到父组件之外的其他DOM 节点下,在DOM中移动一个组件的内容而不改变组件的父级
Suspense 的作用是实现延迟加载和错误处理。在组件中加入Suspense,可以让异步组件可以渲染出加载状态,并且如果异步组件加载时出现错误,它能够处理这些错误
Fragment 用来继承多个子元素的虚拟组件,它的作用时可以解决在vue2中,使用 v-for 迭代元素时需要添加一个包装元素的问题
vue3 使用 WeakMap 来处理循环引用问题 https://aihongxin.com/9739.html
vue3中的setup()函数是用来代替vue2中的data、methods、computed等选项的,它可以用来创建响应式数据和添加需要在模版中使用的方法
defineAsyncComponent 异步组件是通过将组件定义为返回 Promise 的函数来创建的,动态导入,按需加载,代码分割
5. vue3 生命周期(挂载阶段、更新阶段、销毁阶段)
1. setup:替代了 beforeCreate 和 created ,用于数据初始化
2. onBeforeMount:组件将要挂载,在挂载开始之前被调用,相关的 `render` 函数首次被调用。- 此时虚拟 DOM 已经创建,但尚未渲染到页面上,`$el` 属性还不可用。
3. onMounted:组件挂载,在实例挂载到 DOM 之后被调用,此时可以访问到 `this.$el`。- 通常在这个阶段进行 DOM 操作、添加事件监听器等。
4. onBeforeUpdate:组件将要更新,在数据更新时调用,发生在虚拟 DOM 打补丁之前,- 可以在这个阶段访问到旧的 DOM,但新的虚拟 DOM 尚未应用。
5. onUpdated:组件更新,- 在数据更新后,虚拟 DOM 重新渲染并打补丁到 DOM 之后调用。- 通常在这个阶段进行 DOM 操作,但需要注意避免在此处修改状态,以免引发无限循环更新。
6. onBeforeUnmount:组件将要卸载,- 在卸载组件实例之前调用,此时组件实例仍然完全可用。- 通常在这个阶段清理资源,如取消定时器、解除事件监听器等。
7. onUmmounted:组件卸载,- 在组件实例被卸载后调用,此时组件实例的所有指令都被解绑,所有事件监听器被移除,所有子组件实例被卸载。- 通常在这个阶段进行最终的清理工作。
8. onActivated:被包含在 keep-alive 中的组件,用于在组件被缓存后重新激活时执行某些操作
9. onDeactivated:用于组件即将被卸载,a组件切换到b组件,组件消失的时候执行
10. errorCaptured:当捕获到一个来自后代组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串(例如 `'render'` 或 `'watcher'`)。可以返回 `false` 以阻止错误继续向上冒泡。
11. onRenderTracked:在组件的渲染过程中,当某个依赖项被跟踪时调用。帮助你了解哪些响应式依赖项影响了组件的渲染。
12. onRenderTriggered:在组件的渲染被触发时调用。帮助你了解哪些状态变化导致了组件的重新渲染。
三. html+css+js 相关知识点
1. html
2. css
-
src 和 href 的区别
- src指向请求外部资源的来源地址,指向的内容会嵌入到文档中当前标签所在位置,js脚本、img、iframe等元素
- href 意味着超链接,指向网络资源,当浏览器识别到它指向的文件时,就会并行下载资源,不会停止对当前文档的处理,a、link元素
-
px和em的区别
- px是相对于屏幕分辨率而言的,他是一个绝对单位,同时具有一定的相对性。因为在同一个设备上每个像素代表的长度是固定不变的,这点表现的是绝对性。但是在不同的设备之间每个设备像素所代表的长度是可以变化的,这点变现的是相对性
- em是一个相对长度单位,具体的大小需要相对于父元素计算,1em继承父元素的xxpx
-
清除浮动
- clear清除浮动,{clear:both;height:0;overflow:hidden;}
- 给浮动元素父级设置高度
- 万能清除法 ::alter伪元素清浮动
-
两种盒模型以及区别
-
盒模型也称为框模型,就是从盒子顶部俯视所得的一张平面图,用于描述元素所占用的空间。它有两种盒模型,W3C盒模型和IE盒模型(IE6以下,不包括IE6以及怪异模式下的IE5.5+)
-
主要区别是二者的盒子宽度是否包括元素的边框和内边距。当用css给某个元素定义高或宽时,IE盒模型中内容的宽或高将会包含内边距和边框,而W3C盒模型并不会
-
3. js
-
webpack和vite的比较
- webpack 和 vite 都是现代化打包工具
- 从底层来说,vite是基于esbuild预构建依赖,而esbuild是采用go语言编写,因为go语言的操作是纳秒级别,而js是以毫秒计算,所以vite比js编写的打包器快10-100倍。
- webpack: 分析依赖=> 编译打包=> 交给本地服务器进行渲染。首先分析各个模块之间的依赖,然后进行打包,在启动webpack-dev-server,请求服务器时,直接显示打包结果。webpack打包之后存在的问题:随着模块的增多,会造成打出的 bundle 体积过大,进而会造成热更新速度明显拖慢。
- vite: 启动服务器=> 请求模块时按需动态编译显示。是先启动开发服务器,请求某个模块时再对该模块进行实时编译,因为现代浏览器本身支持ES-Module,所以会自动向依赖的Module发出请求。所以vite就将开发环境下的模块文件作为浏览器的执行文件,而不是像webpack进行打包后交给本地服务器。
-
重排和重绘的区别
- 重排:部分渲染树或者整个渲染树需要重新分析并且节点尺寸需要重新计算,表现为重新生成布局,重新排列元素,当浏览器完成重排之后,屏幕上部分内容也会受到重排影响。重排的性能影响更大
- 重绘:由于节点的几何属性发生改变或者由于样式发生改变,例如改变元素背景色时,屏幕上的部分内容需要更新元素的外观被改变
- 重绘不一定重排,但是重排一定会出现重绘
3.宏任务和微任务
- 宏任务包括:setTimeout setInterval Ajax dom事件
- 微任务:Promise async/await
- 微任务比宏任务的执行时间要早
4.js基本数据类型 string number null undefined boolean object biglnt symbol
- bigInt 新加入的一个数据类型,大整数
- Object
- Object.assign 拷贝对象,第一个是目标对象,拷贝后所有属性和方法都会存到target里,后面的参数可以传多个对象,如果有相同的属性则看参数位置,哪个位置越靠后,就用哪个的属性
- Object.create 创建对象,第一个参数为原型对象,是必传的参数,第二个参数是属性对象,也就是对象的属性是一个对象,如name:{} 非必传参数;Object.create()创建的对象会有属性对象的约束,通过属性对选哪个的参数规定约束条件,而普通创建方式创建的对象没有约束
- Object.defineProperty() 监听对象属性(监听多个),一个对象定义一个新属性,或者修改一个对象的现有属性,并返回此对象,也是vue2的双向数据绑定原理。需要传三个参数,第一个参数是需要新增或者修改属性的对象;第二个是属性名,需要引号;第三个是属性描述。后面两个参数相当于把属性对象拆开了
- Object.is 比较两个值是否为同一个值
5.window.onload 和 $(document).ready()的区别,执行先后顺序
1. window.onload 必须等到页面内包括图片的所有元素加载完毕后才能执行
2.$(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕。通常简写为
四. 浏览器相关知识点
1. 前端性能优化
-
HTTP请求优化:较少http请求次数、减少数据请求量和缓存三个方面
-
减少http请求包括和合并css\js文件、压缩图片大小、避免使用多个域名;较少数据量请求降低网络带宽消耗,提高页面加载速度,压缩js\css文件,避免过多html标签节点嵌套
-
根据网站优化需求使用ETag头信息等方式来实现强缓存和协商缓存
-
资源加载优化主要分为异步加载js、延迟加载图片、使用CDN等方式;延迟加载图片避免在页面加载时候请求大量图片,降低网络带宽消耗,提高页面加载速度,期间可以采用骨架屏等方式来提高用户体验;使用CDN加速。即利用CDN将资源分发到离用户更近的服务器上,提高资源加载速度。
-
页面渲染优化,主要包括较少DOM操作次数、比秒table布局、采用css动画等;较少dom操作次数,可以减轻浏览器的负担,提高页面渲染速度,主要通过dom元素和一次性对dom元素进行修改来实现;避免使用table布局,table布局牵一发而动全身,修改一个小标签会使得页面渲染速度变慢,建议使用div+CSS布局或者flex布局。使用CSS动画代替JavaScript动画。CSS动画可以减少JS操作DOM的次数,提高页面渲染速度。
-
代码优化,避免使用全局变量、优化重复执行代码两个方面;过多的全局变量会占用过多内存空间,影响页面性能,为此我们在使用命名空间避免全局变量污染或者将全局变量封装在闭包中;将重复执行的代码进行优化。将重复执行的代码进行优化可以减少代码运行时间,提高页面渲染速度,通过缓存DOM元素、事件委托等形式都可以实现。
-
前端性能优化是提高用户体验的重要手段。本文从HTTP请求优化、资源加载优化、页面渲染优化和代码优化四个方面介绍了常见的前端性能优化方法。
2. 强缓存
-
常见一个epress服务器,服务器端返回头设置,设置本地缓存的秒数 res.set({"cache-control": "max-age=2"});
-
浏览器审查时,重复请求,会发现被强缓存在本地的2秒内都会从本地缓存请求(disk cache),2秒缓存过期后会重新向服务区发送请求
3. 协商缓存
- 一般等强缓存过期后,再次请求时将会从去服务器请求。此时请求头会生成一个与响应头对应的属性,来验证文件是否修改,如若修改则返回最新文件,未修改则返回304不反回包体,提示浏览器继续使用原来保存的缓存。
协商缓存有两种
-
第一种 Last-Modified和If-Modified-Since,我们保留两秒的强缓存,加上Last-Modified,即文件的最后修改时间戳。当浏览器每次去服务器请求,会将响应头的Last-Modified记录,也就是浏览器进行下一次请求时,能够知道上次的Last-Modified,记得上次服务端文件的修改时间。这意味着什么呢?
-
连续请求时,首先会进行强缓存,2s缓存过期后,去服务器时,请求头会自动带上If-Modified-Since,这个字段也就是上次请求响应头中的Last-Modified。此时响应头仍然有一个Last-Modified最后修改时间,而请求头的If-Modified-Since是上次请求返回的最后修改时间,会对这两个值进行对比。若是在该请求之前,服务器文件被修改过了,Last-Modified则更新了,会比If-Modified-Since时间更新,则表示请求文件被修改了,否则未修改。未修改则返回304,表示浏览器可继续用原来的缓存内容。
-
第二种 ETag和If-None-Match
-
ETag代替了Last-Modified作为文件最后的标识,是一个随机生成的字符串。If-None-Match会记录上次请求获取的ETag。(ETag优先级比Last-Modified高)
-
文件修改了,但是内容没有变动,也会导致Last-Modified更新,此时没达到使用缓存的目的。ETag与Last-Modified不同,返回内容不变的话,ETag知道文件修改了等于没修内容改不会改变
4. 跨域总结
- 前端使用jsonp和反向代理;后端跨域用请求头和cors中间件跨域
- 前端通过proxy配置代理
5. 反向代理是什么
- 概念:在前端的服务器中短暂的开启一个后端,让这个后端帮助我们请求数据,然后在返回给前端