前端复健笔记1

1.vite里source-map配置有什么作用

Vite 中,source-map(源码映射)配置的核心作用是‌将构建或编译后的代码映射回原始源代码‌,从而在浏览器开发者工具中直接查看和调试原始的 TypeScript、JSX、SCSS 等源码,而非压缩或转译后的产物代码,方便设置断点、查看变量,大幅提升问题排查效率。配置文件:vite.config.js,值:true(生成 .map 文件,并在 bundle 中添加 //# sourceMappingURL= 注释) | false | hidden(生成 .map 文件,但‌不添加‌注释) | inline(Source Map 内联到 JS 文件中(作为 data URI))。

import { defineConfig } from 'vite';

export default defineConfig({
  build: {
    sourcemap: process.env.NODE_ENV === 'production' ? 'hidden' : true
  }
});

Vite 在 vite dev 模式下默认使用 inline-source-map,无需额外配置即可调试 TS/SCSS 等源码。

‌开发环境‌:保持 sourcemap: true(默认),确保快速精准调试。

‌生产环境‌:若无错误监控系统 → sourcemap: false;若使用 Sentry 等工具 → sourcemap: 'hidden',并上传 .map 文件至监控平台。

大型项目‌:结合 rollupOptions.output.sourcemapExcludeSources 减少 .map 文件体积。

 

2.vue-router history模式上线时需要注意什么事项

①后端服务器配置重定向规则。History模式依赖 HTML5 History API,URL无#,刷新或直接访问路由时会向服务器发送请求。若服务器未配置,将因找不到对应静态资源返回 ‌404‌。需将所有前端路由请求回退至 index.html,由 Vue Router 接管。

②正确设置 base 路径(如部署在子目录)‌。若应用部署在非根域名下(如 https://example.com/my-app/),需在创建 Router 实例时指定 base:

const router = createRouter({
  history: createWebHistory('/my-app/'), // Vue 3
  // 或
  mode: 'history',
  base: '/my-app/',
  routes
});

  

③检查资源路径引用方式‌,确保 index.html 中引入的 CSS、JS、图片等资源使用‌绝对路径‌(以 / 开头),避免因路由层级导致 404。

④验证打包配置(如使用 Vue CLI 或 Vite)‌。‌Vue CLI‌:确保 publicPath 为 '/'(默认)或与部署路径一致;Vite‌:检查 base 配置。

// vue.config.js
module.exports = {
  publicPath: process.env.NODE_ENV === 'production' ? '/my-app/' : '/'
};

  

// vite.config.js
export default defineConfig({
  base: '/my-app/'
});

  

⑤上线前务必在浏览器中直接访问非首页路由(如 /about)并刷新,确认是否正常加载。

 

3.scss中除了变量还有哪些常用语法

①嵌套规则(Nesting)‌。允许将子选择器嵌套在父选择器内部,使代码结构更清晰、贴近 HTML 层级。

②混合宏(Mixins)。可定义可重用的样式块,支持参数和默认值,类似函数。

③继承(@extend)。一个选择器可以继承另一个选择器的所有样式,减少重复代码。

④函数(Functions)。支持内置函数(如 lighten()、darken()、rgba() 等),也支持自定义函数。

⑤控制指令(Control Directives)。包括条件语句(@if / @else)和循环(@for、@each、@while),用于动态生成样式。

⑥占位符选择器(Placeholder Selectors)。以 % 开头,定义不会直接输出的可继承样式,常用于抽象公共样式。

⑦导入(@import)。可将多个 SCSS 文件合并编译,支持模块化开发。

⑧插值(Interpolation)。使用 #{} 在选择器、属性名或值中插入变量。

‌⑨默认变量(!default)。设置变量的默认值,允许后续覆盖。

⑩注释(Comments)。支持单行(//,不输出到 CSS)和多行(/* */,会保留)注释。

⑩①属性嵌套(Nested Properties)。对于具有相同前缀的属性(如 border、font),可进行嵌套写法。

示例:

.nav {
  ul { margin: 0; padding: 0; }
  li { display: inline-block; }
  a { color: blue; }
}

@mixin border-radius($radius: 5px) {
  border-radius: $radius;
}
.box { @include border-radius(10px); }

%btn { padding: 10px; border: none; }
.btn-primary { @extend %btn; background-color: blue; }

@function px-to-rem($px, $base: 16px) {
  @return ($px / $base) * 1rem;
}
.text { font-size: px-to-rem(18px); }

@for $i from 1 through 3 {
  .col-#{$i} { width: 100% / $i; }
}

%center { display: flex; justify-content: center; }
.container { @extend %center; }

@import 'variables';
@import 'buttons';

$property: margin;
.box { #{$property}: 10px; }

$color: blue !default;
$color: red; // 覆盖默认值

.box {
  font: {
    family: Arial;
    size: 16px;
  }
}

  

4、【JS】对闭包的理解

闭包就是在一个内层函数中访问到其外层函数的作用域。在 JavaScript中,每当创建一个函数,闭包就会在函数创建的同时被创建出来,作为函数内部与外部连接起来的一座桥梁。

闭包的优缺点:优点:1:变量长期驻扎在内存中,可以重复使用变量;2:闭包可以实现局部变量,避免全局变量的污染;3:可用于声明私有函数和变量。缺点:1.滥用闭包会造成内存泄露;2.性能损失大。

闭包的工作原理:1.‌函数的作用域‌:在JavaScript中,每个函数都有自己的作用域。当一个函数在其内部创建另一个函数时,内部函数会捕获其外部函数的变量。2.变量的生命周期‌:通常,当一个函数执行完毕后,其局部变量会被销毁。但当内部函数被返回或以其他方式被外部访问时,这些变量不会被销毁(无法被垃圾回收机制回收),因为它们被内部函数“捕获”了。

闭包的作用:私有化变量、模块化、缓存、防抖节流、循环绑定事件。

防抖示例:

function debounce(fn, delay) {
  let timer = null;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

  

5.事件循环(Event Loop)

事件循环是由一个或以上的任务队列组成的。由于 JavaScript 是单线程语言,所以在 JS 中所有的任务都需要排队执行,这些任务共同组成了任务队列,依次排队执行的过程,形成一个执行栈。在任务队列中,最先执行是同步任务。

同步任务就是当上一个任务执行完成后,接下来可以立即执行的任务。它们在主线程上依次排队执行,直到清空。

异步任务就是需要等待被通知才以执行的任务,它们不会直接进入主线程执行,而是进入到微任务队列或下一次事件循环中的任务队列进行等待。

任务队列中遇到的宏任务将进入到下一次事件循环的任务队列,而微任务则会被放入到本次事件循环的微任务队列中。

异步任务分为宏任务和微任务:

常见宏任务:script、setTimeout、setInterval、document.appendChild()

常见微任务:Promise.then/catch/finally、MutationObserver、queueMicrotask

执行顺序:同步 → 微任务 → 渲染 → 下一个宏任务

 

6.promise封装接口返回的时候,如何串联后续流程(如另一个接口)

常见方法:

①使用.then()链式调用:每个.then()接收上一个Promise的成功结果,并返回一个新的Promise,从而可以无限串联。例如,先通过fetch获取数据,然后解析JSON,最后处理业务数据。

②使用async/await语法:在支持async/await的环境中,使用await关键字等待每个Promise解决,实现串行执行,代码更简洁。

③封装接口调用:可以将重复的Promise代码封装成函数,减少冗余代码。例如,针对同一个接口的多次嵌套调用,可以封装成函数进行调用。

④使用Promise.all():当需要同时处理多个异步请求并控制返回结果的顺序时,可以使用Promise.all()。它接收一个Promise数组,并返回一个新的Promise,当所有输入的Promise都解决后,新的Promise也解决,并返回一个包含所有结果的数组。

⑤使用Promise.race():如果只需要返回最快执行完成的Promise的结果,可使用Promise.race()。它接收一个Promise数组,返回一个新的Promise,当第一个输入的Promise解决或拒绝时,新的Promise也解决或拒绝,并返回该结果。

 

7.深拷贝与浅拷贝相关

JavaScript中,对象和数组是引用类型,这意味着将它们赋值给一个变量或者作为函数参数传递时,实际上是在传递一个指向内存中对象的引用,而不是对象本身的副本。

①浅拷贝:只复制对象的第一层属性。也就是说,如果原始对象的属性是基本类型(如数字、字符串、布尔值),那么浅拷贝会复制这些值,且完全独立互不影响;但如果属性是引用类型(如数组、对象、函数),那么拷贝的只是引用,而不复制引用指向的内存地址中的数据,引用类型字段指向同一对象,修改会互相影响。

浅拷贝的方法:Object.assign();展开运算符(...);slice()方法【返回一个新数组,不改变原数组,但若数组包含对象,对象引用仍共享】……

②深拷贝:深拷贝会创建一个全新的对象,并且递归地复制所有属性,使得原始对象和拷贝对象完全独立,互不影响。深拷贝后的对象中所有的属性都是新的引用,即使属性是引用类型,也会被完全复制。

深拷贝的方法:JSON.parse(JSON.stringify(obj))【不能处理函数、undefined、循环引用、特殊对象(如Date、RegExp)等】;lodash的cloneDeep()……

 

8.computed和watch

相同点:

  • 本质上都是一个watcher实例,都通过响应式系统与数据,页面建立通信,只是行为不同
  • 计算属性和监听属性对于新值和旧值一样的赋值操作,都不会做任何变化,不过这一点的实现是在响应式系统完成的。
  • 都是以Vue的依赖追踪机制为基础的

不同点:

  • 机制不同:computed是‌计算属性‌,基于响应式依赖自动缓存派生值,依赖不变时直接返回缓存结果(被动更新,性能更好),必须有返回值。watch是‌侦听器‌,用于监听特定数据变化并执行副作用操作(如异步请求、复杂逻辑),无缓存机制,主动更新。
  • 使用场景不同:computed用于需要计算时(如拼接展示、过滤列表);watch用于需要在数据变化时执行异步操作时(比如发送网络请求)、需要执行一些开销较大的操作,但又不需要实时更新UI时(比如监听浏览器的URL变化)。
  • computed支持缓存、不支持异步、必须同步返回值‌;watch:无缓存、支持异步、可深度监听对象/数组内部变化。

computed有什么场景是值发生了变化,但是结果没有被更新:

  • ‌直接通过索引修改数组元素‌
  • 修改数组长度‌(如:arr.length = newLength)
  • 在对象上动态添加新属性‌(若对象不是响应式的,或属性在初始化时不存在,直接赋值(如 obj.newProp = value
  • 使用非响应式对象替换响应式对象‌(如:state.data = { ... },若新对象不是通过 reactive() 或 ref() 创建,则会丢失响应式连接 ‌‌)
  • 在 computed 中读取了未被正确追踪的属性‌(如解构响应式对象:const { name } = this.user,此时 name 是普通变量,脱离了 Vue 的响应式系统 ‌‌
  • 依赖的值是 props 中未在 data/setup 中声明的字段‌
  • 使用了 Object.freeze() 冻结的对象‌(冻结后的对象属性变化不会触发响应式更新 ‌‌
  • computed 返回的是引用类型,但内部结构变化未通过响应式 API 触发‌(如仅修改了 reactive 对象中的普通属性,但该对象本身未被正确初始化为响应式 ‌‌

 

9.data为什么是一个函数,并且要返回一个对象

①为什么是一个函数

为了确保每个组件实例拥有‌独立的状态‌,避免数据共享带来的副作用。

Vue 组件通常会被多次复用(如多个按钮、卡片等),如果 data 是一个普通对象,所有组件实例会共享同一个引用,导致一个实例修改数据时,其他实例也会受到影响。当 data 是函数时,Vue 在创建每个组件实例时都会‌调用该函数‌,从而获得一个‌全新的数据对象‌,彼此隔离,互不干扰 ‌‌

②为什么必须返回一个对象

Vue 的响应式机制(基于 Object.defineProperty 或 Proxy)只能对‌对象的属性‌进行数据劫持。返回对象后,Vue 会将其所有属性转换为 getter/setter,实现视图自动更新 ‌‌。且对象可以包含多个属性,方便组织和访问组件状态 ‌‌

 

10.vue2的生命周期

创建阶段:

  • beforeCreate:实例初始化之后,数据观测和事件配置之前被调用,通常进行全局配置或初始化操作。

    特点:data、methods、computed、watch等都不可用;$el属性不可访问;无法访问DOM元素。
    使用场景:添加全局Loading效果

  • created:实例创建完成,可进行数据初始化操作,如发起网络请求获取初始数据,但DOM尚未生成。

    特点:data、methods、computed、watch已完全可用;可以访问响应式数据;$el不可用,DOM未渲染
    使用场景:【最常用的钩子之一】数据请求,初始化非响应式数据,设置定时器、订阅事件

挂载阶段:

  • beforeMount:挂载开始之前,模板已编译成render函数,但还未挂载到页面上。

    特点:模板已编译成render函数;$el属性存在,但内容是原始模板;虚拟DOM已创建,但未替换真实DOM
    使用场景:可以在挂载前做最后的修改

  • mounted:实例被挂载到DOM后调用,可访问DOM元素,常用于初始化第三方库或操作DOM。

    特点:$el已挂载,可以访问真实DOM;子组件也已挂载完成;可以安全地操作DOM
    使用场景:【最常用的钩子之一】操作DOM元素,初始化第三方库,获取组件/元素的实际尺寸和位置,发起不依赖数据初始化的请求

更新阶段:

  • beforeUpdate:数据更新时,虚拟DOM重新渲染和打补丁之前调用,可访问更新前的DOM状态。

    特点:数据已更新,但DOM还未更新;可以获取更新前的DOM状态;适合在DOM更新前读取现有状态
    使用场景:获取更新前的DOM状态(如滚动位置),在DOM更新前进行清理工作

  • updated:数据更改导致的虚拟DOM重新渲染和打补丁后调用,可操作更新后的DOM。

    特点:DOM已更新完成;可以获取更新后的DOM状态;子组件也已更新完成
    使用场景:依赖DOM更新的操作(如滚动加载更多),第三方库重新渲染,保存DOM状态

销毁阶段:

  • beforeDestroy:实例销毁之前调用,可进行清理工作,如解绑自定义事件、清除定时器等。

    特点:组件即将被销毁;所有data、methods、computed等仍然可用;是清理资源的最后时机;
    使用场景:必须使用,用于清理资源:清除定时器、取消订阅、解绑事件,避免内存泄漏

  • destroyed:实例销毁后调用,所有事件监听器和子实例已被移除。

    特点:所有指令、事件监听器已解绑;子组件也已销毁;实例不再响应式
    使用场景:一些最终的清理通知

 

11.Vue3的Composition API

Composition API(组合式API)解决了传统Options API中逻辑分散、代码复用困难、大型组件难以维护的痛点,让代码更聚合、更易复用、更易类型推导(完美适配 TypeScript )。它的主要组成部分:
ref:【基础类型响应式(核心API)】用于创建一个响应式引用,为字符串、数字、布尔值、null、undefined等基础数据类型创建响应式对象,也可用于引用类型。
reactive:【引用类型响应式(核心API)】用于为对象、数组等引用数据类型创建深层响应式对象,当对象内的属性发生改变时,所有依赖该对象的代码都会被重新执行。
toRefs:解构响应式对象不丢失响应性,常用于封装组合式函数、解构props。
computed:基于响应式数据生成缓存的派生数据,用法和Vue2一致。
watch:监听响应式数据变化,执行副作用操作(如请求、DOM 操作)。支持监听:ref、reactive、多个数据源、深度监听。
watchEffect:自动依赖侦听。优势:无需手动指定监听目标,自动收集依赖,代码更简洁。场景:简单的监听逻辑、初始化执行一次。

此外,Composition API 还支持自定义Hook和函数式组件,提高了代码的复用性和测试性。所有Composition API 都在<script setup>中使用,这是 Vue3 推荐的语法糖,无需手动导出、无需写 return,代码更简洁,组件中所用到的数据、方法等均要配置在 setup 中。

 

12.React常用Hooks

1. useState:给组件添加状态,状态变化时界面自动更新。
2. useEffect:处理副作用,如发请求、设定时器、操作DOM等,替代类组件的生命周期。
  - 不传依赖数组:每次渲染都执行。
  - 传空数组:只在首次渲染时执行一次。
  - 传依赖项:依赖变化时才执行。
3. useContext:跨组件传值,避免props一层层往下传递。
  - 适合全局状态如主题、用户信息、语言配置。
4. useRef:存储不触发更新的值,或获取 DOM 元素引用。
  - 修改`ref.current`不会让组件重新渲染。
5. useMemo/useCallback:性能优化,缓存计算结果或函数,避免不必要的重复渲染。
6. useReducer:处理复杂状态逻辑,类似Redux的简化版。
7. useTransition/useDeferredValue:React 18 新增,处理优先级不同的更新任务,提升用户体验。

 

posted @ 2026-05-10 21:37  芝麻er  阅读(33)  评论(0)    收藏  举报