不是吧,不是吧,前端面试又出新玩法了?!

前端新的面试题又来咯

拖拽与 DOM

问题 1:拖拽过程中,如果原本的元素消失了,onDrop 还能触发么?具体表现是什么? 答案: 能触发。onDrop 事件会在放置的目标元素上触发。具体表现是:拖拽源元素在拖拽过程中被移除(如设置为 display: none 或从 DOM 中删除),只要鼠标在有效的放置目标上释放,onDrop 仍会触发。但是,event.dataTransfer 对象中关于拖拽源的数据可能变得不可靠或丢失。

问题 2:如何改变拖拽预览图? 答案: 使用 DataTransfer.setDragImage() 方法。

javascript 复制代码
element.addEventListener('dragstart', (e) => {
  // 创建一个自定义图像元素
  const dragImage = document.createElement('div');
  dragImage.textContent = '自定义预览';
  dragImage.style.background = 'blue';
  document.body.appendChild(dragImage);

  // 设置拖拽预览图,后两个参数是鼠标相对于预览图的偏移量
  e.dataTransfer.setDragImage(dragImage, 10, 10);
});

问题 3:如何让拖拽预览图有圆角? 答案: 为你在 setDragImage 中使用的自定义预览元素添加 CSS border-radius 属性即可。

css 复制代码
#customDragImage {
  border-radius: 10px;
}

ECharts 与响应式布局

问题 4:你用了 echart,如何让 echart 的内容跟随容器大小而变化?onResize 的时候要怎么做? 答案: 调用 ECharts 实例的 .resize() 方法。

javascript 复制代码
// 初始化图表
const myChart = echarts.init(document.getElementById('chart-container'));

// 监听窗口 resize 事件
window.addEventListener('resize', () => {
  myChart.resize();
});

问题 5:如果有可伸缩侧边栏之类的,导致容器因为其他原因发生了改变,应该用什么事件监听? 答案: 使用 ResizeObserver API。它可以监听任意 DOM 元素尺寸的变化,而不仅仅是窗口。

javascript 复制代码
const resizeObserver = new ResizeObserver(entries => {
  for (let entry of entries) {
    myChart.resize();
  }
});
resizeObserver.observe(document.getElementById('chart-container'));

部署、缓存与 CDN

问题 6:如果是 toc 产品,后端为 index.html 设置了 1 h 的 max age,请问从你重新构建代码发布,大概多久之后,所有用户都可以看到新界面? 答案: 理论上最长需要 1 小时(max-age 时间)加上 CDN 边缘节点的缓存过期时间。但由于用户浏览器缓存、CDN 配置(如是否启用了 stale-while-revalidate)等因素,实际时间可能更长或更短。保守估计,1-2 小时内所有用户会逐渐看到新界面。

问题 7:如果用户访问出现了白屏,是什么原因? 答案: 常见原因包括:

  1. JavaScript 加载失败: 资源路径错误、CDN 故障、网络问题。
  2. JavaScript 执行错误: 新版本代码存在语法错误或运行时错误,导致应用初始化失败。
  3. 资源加载超时。
  4. 浏览器兼容性问题。
  5. 入口 HTML 文件被缓存(如 index.html),但引用的新版本 JS/CSS 文件无法加载。

问题 8:toc 产品大量使用 cdn,请问 cdn 的定价大概多少?针对这样的定价策略,前端应该进行什么样的优化? 答案:

  • 定价: 主流云厂商(阿里云、腾讯云)的 CDN 通常按 流量HTTP 请求次数 计费。流量费用约 0.1 - 0.3 元/GB,请求费用约 0.01 - 0.05 元/万次。上传(回源)流量通常比下载(分发)流量贵。
  • 前端优化:
    1. 资源压缩: 启用 Gzip/Brotli 压缩,图片使用 WebP 格式。
    2. 减少请求: 合并小文件(雪碧图)、利用 HTTP/2 多路复用。
    3. 缓存优化: 为静态资源设置长的 Cache-Control max-age,并使用内容哈希命名实现"永不过期"缓存。
    4. 代码分割与懒加载: 只加载当前页面需要的代码。
    5. 使用 CDN 预热功能,将重要资源提前推送到边缘节点。

问题 9:前端应用中?上传贵还是下载贵?上传快还是下载快? 答案: 在 CDN 语境下,上传(回源)通常比下载(分发)贵 。对于普通网络连接,下载速度通常远快于上传速度(家庭宽带上下行不对称)。


HTTP 缓存与多媒体

问题 10:图片设置协商缓存后,浏览器会整体缓存,视频能设置协商缓存么?视频的 http 返回内容与图片有什么区别? 答案:

  • 视频可以设置协商缓存。
  • 区别: 视频通常支持 范围请求(Range Requests) 。HTTP 响应头会包含 Accept-Ranges: bytes,并且在请求部分视频时,状态码是 206 Partial Content 而不是 200 OK。这使得客户端可以只请求视频的某一部分,而不是整个文件。

问题 11:如何降低视频展示的成本? 答案:

  1. 使用高效的视频编码: 如 H.265/HEVC 或 AV1,在相同质量下文件更小。
  2. 自适应码流: 使用 HLS 或 DASH 等技术,根据用户网速动态切换不同清晰度的视频流。
  3. CDN 加速。
  4. 视频压缩与优化: 在可接受的范围内降低码率和分辨率。
  5. 懒加载: 视频进入视口后再开始加载。

设计与视觉

问题 12:既然有那么多 4k,2k,屏幕,为啥设计师的图还是以 1280 为主?是什么原因导致的? 答案: 主要原因:

  1. 历史与兼容性: 1280px 是长期以来最主流和稳定的屏幕宽度基准。
  2. 开发效率: 提供一个标准尺寸便于设计和开发对齐。
  3. 内容可读性: 过宽的单行文本不利于阅读,设计稿更关注核心内容的布局。
  4. 响应式设计: 设计以 1280px 为"桌面端"基准,然后通过响应式规则适配更大或更小的屏幕,而非直接为 4K 设计。

问题 13:高分辨率图片在低分辨率屏幕上为什么会糊?为什么会有图片明明正常但是一旦有动画之后也糊了?遇到这种问题如何解决? 答案:

  • 原因1(高分辨率图在低分辨率屏): 浏览器需要将高像素密度的图片压缩到更少的物理像素上显示,这个"下采样"过程可能导致模糊和细节损失。
  • 原因2(动画后变糊): 浏览器为了动画性能,可能会将动画元素提升到独立的合成层(GPU 渲染)。在层创建或变换过程中,如果处理不当(如不是整数像素移动),抗锯齿算法可能导致暂时性模糊。
  • 解决方案:
    1. 使用 srcsetsizes 属性为不同屏幕提供合适的图片尺寸。
    2. 对动画元素应用 transform: translateZ(0)will-change: transform 来触发 GPU 加速,并确保动画属性(如 transform)的值为整数像素。
    3. 检查图片的原始尺寸是否与显示尺寸匹配。

问题 14:设计师给了一套 SVG 图片,图片在 macos 上显示正常,但在 windows 下十分模糊,是你的代码问题还是设计师出的图片的问题?如果有这样的情况,最后是如何解决的? 答案: 这通常是 代码或环境问题,而非 SVG 源文件问题。SVG 是矢量格式,理论上应在任何分辨率下都清晰。

  • 常见原因与解决方案:
    1. CSS 尺寸问题: 确保 SVG 的容器尺寸是整数像素,避免非整数缩放。width: 100.5px 可能导致模糊。
    2. Viewport 和 ViewBox 不匹配: 检查 SVG 代码中的 viewBox 属性,并确保其与显示尺寸成比例。
    3. 浏览器渲染引擎差异: macOS 和 Windows 的字体渲染和图形抗锯齿算法不同。可以尝试为 SVG 添加 shape-rendering: geometricPrecision; CSS 属性。
    4. 位图嵌入: 如果 SVG 内嵌了模糊的位图,那么在 Windows 上也会模糊。

TypeScript

问题 15:ts 开发下,interface 和对象类型声明可不可以用来声明数组和函数? 答案: 可以。

typescript 复制代码
// 声明数组
interface NumberArray {
  [index: number]: number; // 索引签名
}
type NumberArrayType = number[]; // 更简单的方式

// 声明函数
interface SearchFunc {
  (source: string, subString: string): boolean; // 调用签名
}
type SearchFuncType = (source: string, subString: string) => boolean;

问题 16:如果声明函数,函数名可不可以重复?函数名如果重复,意味着什么? 答案: 在同一个作用域内,不允许 直接声明同名函数(会报错)。但在接口或类中,可以通过 函数重载 来声明多个同名但参数/返回值不同的函数签名。

typescript 复制代码
// 函数重载
function greet(name: string): string;
function greet(age: number): string;
function greet(value: string | number): string {
  // 实现...
}

重复的函数名意味着重载,调用时会根据传入的参数类型来匹配对应的签名。


Vue.js 深度知识

问题 17:如果你用的是 Vue,在 Vue 的 ts 用法中,哪些 api 的用法利用了 ts 这一特性? 答案:

  1. Props 类型定义: 使用 defineProps<{ ... }>() 进行严格的类型检查。
  2. 组件实例类型: 使用 InstanceType<typeof MyComponent> 来获取模板引用(ref)的类型。
  3. Composables 类型推断: refcomputed 会自动推断类型,reactive 也会基于对象字面量推断。
  4. 事件类型定义: 使用 defineEmits<{ ... }>() 来定义和校验组件发出的事件及其载荷。

问题 18:Vue 中,是不是所有情况下,template 都会自动获取 ref 的 .value 属性?如果不是,列举不会自动获取的情况。 答案: 不是所有情况。

  • 会自动解包 .value 的情况:
    • <script setup> 中声明的顶级 ref,在模板中直接使用无需 .value
    • ref 在模板中作为响应式对象的属性时(如 obj.count),如果该 ref 是通过 reactive 访问的,会自动解包。
  • 不会自动解包的情况:
    • 在 Options API 的 data() 函数中返回的对象的属性不是 ref,无需解包。
    • ref数组或 Map 等原生集合类型 的一个元素时,不会自动解包。例如:const list = ref([1, 2, 3]),在模板中使用 list[0] 不会自动解包,需要 list[0].value(但在模板中应避免这样写,通常应解构到响应式对象中)。

问题 19:在 Vue 响应式系统中,给对象的子属性对象赋值一个新对象,是否还有响应式?详细阐述一下。 答案: 有响应式,但需要理解其原理。

javascript 复制代码
const state = reactive({
  nested: { count: 0 }
});

// 这个操作是响应式的
state.nested = { count: 1 }; // Vue 能检测到 `nested` 属性被重新赋值了

Vue 的响应式系统通过 Proxy 跟踪对象属性的访问和设置 。当你给 state.nested 赋一个新值时,Vue 会检测到这个设置操作,并触发相应的更新。同时,新赋值的对象 { count: 1 } 会被自动转换为一个响应式对象。

问题 20:如果你使用 Vue 和 pinia 开发了一个应用,用到了 persist 插件进行持久化,结果发现应用卡顿难以接受,请问卡顿最有可能是什么原因导致的? 答案: 最可能的原因是 持久化的数据量过大或序列化/反序列化操作过于频繁

  • 具体原因:
    1. 大数据量: 将整个庞大的状态树(如大型列表、复杂嵌套对象)持久化到 localStorage(同步 API),每次读写都会阻塞主线程。
    2. 频繁存储: 插件配置为每次状态变化都立即持久化(debounce 配置不合理),导致频繁的同步写入操作。
  • 解决方案:
    1. 只持久化必要的状态,使用 paths 选项排除大数据。
    2. 增加防抖(debounce)时间,减少持久化频率。
    3. 考虑使用异步存储后端,如 sessionStorageIndexedDB(如果插件支持)。

问题 21:Vue 的响应式系统,可否用一个 class 初始化的对象声明 reactive?会有什么后果?(如果他了解 React,问 React 的 useState 可不可以) 答案:

  • Vue: 可以,但不推荐,可能会丢失响应性。

    • 后果: Vue 的 reactive() API 基于 ES6 Proxy。如果一个 class 实例的属性是在构造函数中通过 this.key = value 定义的,Proxy 可以正常工作。但如果属性是在 class 的方法中动态添加的,或者涉及继承链,Vue 可能无法可靠地追踪这些变化。最佳实践是使用普通对象字面量。
    javascript 复制代码
    class MyState {
      constructor() { this.count = 0; } // 可响应
      increment() { this.count++; }     // 可响应
      addNewProp() { this.newProp = 1; } // 可能无法被 Vue 自动追踪
    }
    const state = reactive(new MyState());
  • React: 可以,但极其不推荐。

    • 原因: React 的状态更新依赖于 setState 或 setter 函数触发的重新渲染。直接修改 class 实例的属性(myState.count++)不会触发渲染,因为 React 无法感知到变化。你必须创建一个新的对象引用来驱动更新。

问题 22:Vue 中的 pinia 和 pinia 配合依赖注入使用,与单纯的依赖注入有哪些区别? 答案:

  • 单纯的依赖注入(provide/inject): 是一种直接的父子组件间传递数据/方法的方式。它是局部的 ,需要在上层组件 provide,在下层组件 inject。数据本身不一定是响应式的(除非你提供的是一个 refreactive 对象),并且缺乏像 Pinia 那样的集中式状态管理、DevTools 集成和时间旅行调试能力。
  • Pinia:全局状态管理库。它提供了一个中心化的 store,任何组件都可以导入并使用。状态天生是响应式的,并具有完善的模块化、TypeScript 支持和调试工具。
  • Pinia + 依赖注入: 结合两者,通常是为了 更好的测试和解耦。你可以在根组件提供一个 Pinia store 的实例,然后在子组件中注入它。这样做的好处是,在测试时,你可以轻松地提供一个模拟的 store 实例给组件,而不需要依赖真实的全局 store 实例,使得测试更加隔离和容易。

工程化与业务逻辑

问题 23:如果项目主包太大,有什么方法可以优化? 答案:

  1. 代码分割(Code Splitting): 使用动态 import() 语法实现路由级和组件级懒加载。
  2. Tree Shaking: 确保引入的第三方库支持 ES 模块,并只引入需要的部分。
  3. 分析包体积: 使用 webpack-bundle-analyzer 等工具找出体积过大的模块。
  4. 压缩资源: 使用 Terser 压缩 JS,CssMinimizer 压缩 CSS。
  5. 优化第三方库: 考虑用更轻量的替代品(如 day.js 代替 moment.js)。
  6. 图片等资源外部化。

问题 24:如何解决删除一个项目之后,表格分页为空的问题? 答案: 在成功删除一项后,需要重新计算当前页码。

javascript 复制代码
// 伪代码
const handleDelete = async (id) => {
  await api.deleteItem(id);
  // 删除成功后
  const currentPage = pagination.current;
  const totalAfterDelete = totalCount - 1;
  const pageSize = pagination.pageSize;

  // 如果当前页不再是有效页(例如,最后一页的唯一一项被删除了),则跳回上一页
  if (currentPage > Math.ceil(totalAfterDelete / pageSize)) {
    pagination.current = currentPage - 1;
  }

  // 重新获取数据
  fetchData();
};

问题 25:上传时,假设后端没有用对象存储,你应该如何与后端配合,实现上传和下载进度? 答案:

  • 上传进度: 使用 XMLHttpRequest 或 Axios 等库的进度事件。

    javascript 复制代码
    axios.post('/upload', formData, {
      onUploadProgress: (progressEvent) => {
        const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
        // 更新进度条
      }
    })
  • *** 下载进度: 同样利用进度事件,但需要后端在响应头中正确设置 Content-Length

    javascript 复制代码
    axios.get('/download/file.pdf', {
      onDownloadProgress: (progressEvent) => {
        const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
        // 更新进度条
      },
      responseType: 'blob' // 重要:对于文件下载
    })

HTTP 缓存策略与服务端渲染

问题 26:stale-while-revalidate 这字段出现在 http 什么位置,用来做什么的?它和服务端渲染有什么关系? 答案:

  • 位置: 它是 Cache-Control 响应头的一个指令,例如:Cache-Control: max-age=600, stale-while-revalidate=30
  • 作用:max-age(600秒)过期后,还有一个 stale-while-revalidate(30秒)的"宽限期"。在这30秒内,浏览器会立即使用已过期的缓存(stale) 来响应用户请求,同时在后台向服务器发起验证请求(revalidate) 以获取最新内容并更新缓存。这极大地提升了用户体验,实现了"瞬间加载"。
  • 与 SSR 的关系: 在 SSR 应用中,HTML 页面本身是动态的。如果对 HTML 页面设置 stale-while-revalidate,可以让用户在页面缓存过期后依然能快速看到内容(即使是略微过时的内容),同时在后台获取最新的服务端渲染页面。这完美结合了缓存的性能和 SSR 的 SEO/首屏优势。

问题 27:国内的生态对这个字段的支持程度如何?你会在项目中使用服务端渲染么? 答案:

  • 支持程度: 主流现代浏览器(Chrome, Edge, Firefox, Safari)均已支持。国内移动端浏览器(如 UC、QQ)内核较老,可能存在兼容性问题,需根据目标用户群体决定是否使用。
  • 是否使用 SSR:
    • 会用 SSR 的场景: 对 SEO 有极高要求的 ToC 网站(如官网、博客、电商列表页)、对首屏加载速度有极致追求的应用。
    • 不会用 SSR 的场景: 复杂的后台管理系统、强交互型 Web App、对搜索引擎无需求的内部工具。在这些场景下,SSR 带来的服务器成本和架构复杂性可能得不偿失。

数据迁移与错误处理

问题 28:假设你在 localStorage 或者 indexedDB 中存储了数据结构,但是版本更新后需要用新的数据结构,你会用什么方法进行迁移? 答案: 实施一个版本化迁移策略

  1. 存储版本号: 在存储数据时,同时存储一个版本号(如 dataVersion: '1.0')。
  2. 启动时检查: 应用启动时,读取当前存储的版本号,并与代码中期望的最新版本号比较。
  3. 执行迁移: 如果版本不一致,则按顺序执行从一个版本到下一个版本的迁移函数。
  4. 更新版本号: 迁移成功后,更新存储中的版本号为最新版。
javascript 复制代码
// 迁移函数示例
const migrateUserData = (oldData) => {
  const currentVersion = oldData.version || '1.0';
  if (currentVersion === '1.0') {
    // 从 1.0 迁移到 2.0
    const newData = {
      version: '2.0',
      profile: { ...oldData.userInfo } // 转换数据结构
    };
    localStorage.setItem('userData', JSON.stringify(newData));
    return newData;
  }
  // ... 其他版本迁移
};

问题 29:假设是混合应用,用户可能用着各种历史版本,又该如何迁移? 答案: 迁移策略需要是幂等向后兼容的。

  • 幂等: 同一个迁移函数执行多次的结果应该是一样的。避免因重复执行导致数据错误。
  • 向后兼容: 新版本的代码应该能够读取和理解旧版本的数据结构。在迁移完成前,应用逻辑应能处理新旧两种数据结构。

问题 30:如果用户因为数据迁移出现了白屏,如何定位问题?如何及时补救? 答案:

  • 定位问题:
    1. 错误监控: 接入 Sentry 等错误监控平台,捕获迁移过程中抛出的异常。
    2. 日志记录: 在迁移的关键步骤中加入详细的日志,记录旧版本号、新版本号、迁移结果等。
    3. 用户反馈: 建立用户反馈渠道,收集出现白屏的用户的浏览器版本、操作步骤等信息。
  • 及时补救:
    1. 安全模式: 在迁移代码外围使用 try-catch。如果迁移失败,捕获错误,清除损坏的存储数据或回退到旧版本数据结构,并引导用户重新初始化应用。
    2. 热修复: 如果问题普遍,通过热修复平台紧急下发修复补丁,修正迁移逻辑。
    3. 版本回退: 在严重情况下,可以考虑回退应用版本。

富文本与协作

问题 31:在基础富文本开发中,如果光标跨越了多个节点,如何正确通过 getSelection 进行选取? 答案: 使用 SelectionRange API。

javascript 复制代码
const selection = window.getSelection();
// 获取用户选中的范围
if (selection.rangeCount > 0) {
  const range = selection.getRangeAt(0);
  const startContainer = range.startContainer; // 起始节点
  const startOffset = range.startOffset;       // 起始偏移量
  const endContainer = range.endContainer;     // 结束节点
  const endOffset = range.endOffset;           // 结束偏移量

  // 现在你可以操作这个 range,例如插入节点、获取选中内容等
  const selectedContent = range.cloneContents();
}

问题 32:如果不使用浏览器默认高亮,如何让这些选区高亮起来? 答案: 手动高亮。

  1. 遍历范围内容: 使用 Range.cloneContents().extractContents() 方法获取选区内的 DOM 节点。
  2. 包裹高亮元素: 遍历这些节点,用带有高亮样式(如 background-color: yellow;)的 HTML 元素(如 <mark><span>)将文本节点包裹起来。
  3. 重新插入: 将处理后的节点重新插入到 DOM 中。更高级的做法是使用 CSS.highlights API(实验性)。

问题 33:多人共同编辑的文档,如何保证云端缓存和本地缓存的一致性?这方面如何与后端配合? 答案: 使用 操作转换(OT)冲突-free 复制数据类型(CRDT) 算法。

  • 核心思想: 不是简单地覆盖数据,而是将用户的操作(如"在位置5插入字符'A'")作为指令发送到服务端。
  • 与后端配合:
    1. 版本控制: 每个操作都有一个版本号(或向量时钟)。
    2. 服务端协调: 后端作为中央协调者,接收来自各客户端的操作,进行转换(解决冲突,例如两个用户同时在位置5插入不同字符),然后广播转换后的操作给所有客户端。
    3. 确认机制: 客户端只有收到服务端确认的操作才会应用到本地文档,确保最终一致性。

浏览器安全与图形学

问题 34:如果使用浏览器用户标识,并进行插件开发,插件中有个 iframe,请问 iframe 里面的用户标识和插件的用户标识,是同一个,还是不同的? 答案: 这取决于 iframe 的源(origin)。

  • 同源 iframe: 是同一个。它们共享相同的 origin,因此共享相同的存储(如 localStorage)、Cookie 和用户标识。
  • 跨域 iframe: 是不同的 。由于浏览器的同源策略,插件的上下文和跨域 iframe 的上下文是相互隔离的。它们拥有独立的存储空间和用户标识。通信需要通过 postMessage API。

问题 35:如何实现提取图片主题颜色和分级颜色的功能,如果实现了,对后端有什么要求? 答案:

  • 前端实现:

    1. 使用 Canvas API 将图片绘制到画布上。
    2. 通过 getImageData() 方法获取像素数据(一个包含 RGBA 值的巨大数组)。
    3. 使用聚类算法(如 K-means)或量化算法对像素颜色进行分组,找出主要的颜色簇。
    javascript 复制代码
    const img = new Image();
    img.onload = function() {
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      ctx.drawImage(img, 0, 0);
      const imageData = ctx.getImageData(0, 0, img.width, img.height).data;
      // 分析 imageData,提取主题色
    };
    img.src = 'image.jpg';
  • 对后端的要求: 如果在前端处理大图片可能性能不佳,可以将此任务卸载到后端。后端需要提供相应的图片处理接口,接收图片文件,返回分析出的主题色数组。这要求后端有强大的图片处理能力和计算资源。

问题 36:hsl 和 oklch 颜色表示法相比 rgb 好在哪里?有哪些前端 UI 框架使用了这些色彩表示法? 答案:

  • 优势:
    • HSL(Hue, Saturation, Lightness): 更直观,易于人类理解和调整。比如,想得到一个更深的蓝色,只需减小 L(明度)值。
    • OKLCH: 是基于 OKLab 色彩空间的改进版,比 HSL 和 RGB 在感知上更均匀。这意味着,颜色数值上的等量变化,会带来人眼感知上接近的视觉变化。这对于生成和谐的调色板、无障碍设计和主题切换至关重要。
  • 使用框架:
    • Tailwind CSS v3.x 已在其默认调色板中使用了 OKLCH。
    • Adobe 的 Spectrum 设计系统也在向 OKLCH 迁移。
    • 许多新兴的 CSS-in-JS 库和主题系统开始支持 OKLCH。

问题 37:如果要你利用其做一个多主题系统,你会如何设计架构? 答案: 采用 CSS 变量(Custom Properties) + OKLCH/HSL 的架构。

  1. 定义设计令牌: 使用 OKLCH 定义一套核心的颜色、间距、字体等变量。

    css 复制代码
    :root {
      --primary-color: lch(60% 60 250); /* 使用 OKLCH */
      --text-color: lch(20% 5 250);
      --spacing-unit: 8px;
    }
  2. 主题派生: 通过覆盖这些 CSS 变量的值来创建不同的主题。

    css 复制代码
    .theme-dark {
      --primary-color: lch(80% 50 250);
      --text-color: lch(90% 5 250);
    }
  3. 组件使用: 在所有组件中只使用这些设计令牌变量。

    css 复制代码
    .button {
      background-color: var(--primary-color);
      color: var(--text-color);
      padding: calc(var(--spacing-unit) * 2);
    }
  4. 动态切换: 通过 JavaScript 切换根元素或 body 元素的类名,即可实现主题的动态切换。OKLCH 的感知均匀性保证了不同主题下的视觉和谐度。


HTTP RESTful API

问题 38:http RESTFUL 请求中,put 和 post 分别代表什么?put 分别代表新增和修改的情况下,前后端的数据和逻辑会有怎样的差异? 答案:

  • POST: 用于创建 新资源。它是非幂等 的(多次调用会产生多个资源)。通常,URL 指向的是资源集合(如 /api/users),请求体包含新资源的详细信息。响应通常返回 201 Created 和新资源的 URI。
  • PUT: 用于更新/替换 现有资源,或在客户端知道资源最终 URI 时创建 资源。它是幂等 的(多次调用效果相同)。
    • 用于修改(更新): URL 指向一个特定的资源(如 /api/users/123)。请求体应包含该资源的完整表示 。后端逻辑是用请求体提供的数据完全替换 目标资源。如果资源不存在,可以返回 404 Not Found,或者根据约定创建它(返回 201 Created)。
    • 用于新增(创建): 客户端明确指定新资源的 URI(如 /api/users/123)。后端检查该 URI 是否存在资源。如果不存在,则创建;如果已存在,则完全替换。这要求客户端拥有分配资源 ID 的能力。
相关推荐
持续升级打怪中11 小时前
ES6 Promise 完全指南:从入门到精通
前端·javascript·es6
AC赳赳老秦11 小时前
前端可视化组件开发:DeepSeek辅助Vue/React图表组件编写实战
前端·vue.js·人工智能·react.js·信息可视化·数据分析·deepseek
小白冲鸭11 小时前
苍穹外卖-前端环境搭建-nginx双击后网页打不开
运维·前端·nginx
wulijuan88866611 小时前
Web Worker
前端·javascript
深念Y11 小时前
仿B站项目 前端 3 首页 整体结构
前端·ai·vue·agent·bilibili·首页
IT_陈寒11 小时前
React 18实战:这5个新特性让我的开发效率提升了40%
前端·人工智能·后端
深念Y12 小时前
仿B站项目 前端 5 首页 标签栏
前端·vue·ai编程·bilibili·标签栏·trae·滚动栏
克里斯蒂亚诺更新12 小时前
vue3使用pinia替代vuex举例
前端·javascript·vue.js
Benny的老巢12 小时前
用 Playwright 启动指定 Chrome 账号的本地浏览器, 复用原账号下的cookie信息
前端·chrome
yuniko-n12 小时前
【牛客面试 TOP 101】链表篇(一)
数据结构·算法·链表·面试·职场和发展