乐清做网站公司哪家好/抖音视频seo霸屏

乐清做网站公司哪家好,抖音视频seo霸屏,做设计网站,玄武区网站建设前端开发岗模拟面试题套卷A答案及解析(一)技术面部分 (一)技术面 一、JavaScript核心技术(ES6+) 1-1、实现防抖函数 function debounce(fn, delay) {let timer = null;return function(...args) {clearTimeout(timer); // 清除已有定时器timer = setTimeout(() =>…

前端开发岗模拟面试题套卷A答案及解析(一)技术面部分

(一)技术面

一、JavaScript核心技术(ES6+)

1-1、实现防抖函数
function debounce(fn, delay) {let timer = null;return function(...args) {clearTimeout(timer); // 清除已有定时器timer = setTimeout(() => { fn.apply(this, args); // 绑定正确this}, delay);};
}
// 应用场景:搜索框输入联想、窗口resize事件
1-2、其应用场景解释

防抖函数(debounce)核心作用是 限制高频触发的函数执行频率,确保连续多次触发时,只在最后一次触发后延迟执行一次目标函数。

postscript:
代码逐行解释

1、let timer = null
利用闭包特性保存定时器标识,保证多次调用时共享同一个 timer。
2、clearTimeout(timer)
每次触发时,先清除上一次的定时器,重置倒计时。
3、setTimeout(() => { fn.apply(this, args) }, delay)
延迟 delay 毫秒后执行目标函数 fn,并通过 apply 确保 this 指向和参数传递正确性。

核心特性

特性说明
延迟执行触发后等待 delay 时间再执行
重置机制新触发会覆盖旧定时器
上下文绑定通过apply保留原函数 this
1-3 应用场景举例

1、搜索框输入联想

  • 问题:用户连续输入时,每次按键都会触发搜索请求,导致请求爆炸。
  • 解决:防抖控制在用户停止输入 300ms 后发送请求。
    示例代码:
const searchInput = document.getElementById('search');
searchInput.addEventListener('input', debounce(function() {// 发送搜索请求
}, 300));

2、窗口resize事件

  • 问题:调整窗口大小时频繁触发重绘逻辑,引发性能问题。
  • 解决:防抖确保只在调整结束后计算布局。
window.addEventListener('resize', debounce(function() {// 更新布局
}, 200));

3、按钮防重复提交

  • 问题:用户快速点击按钮导致重复提交请求。
  • 解决:防抖屏蔽短时间内的多次点击。
submitBtn.addEventListener('click', debounce(function() {// 提交表单
}, 1000));

与节流(throttle)的区别

区别项&技术名防抖(debounce)节流(throttle)
逻辑只执行最后一次触发固定时间间隔执行一次
场景输入联想、resize滚动事件、鼠标移动

postscript:
回答得分点

1、正确识别防抖函数(占 40%)
✅ 明确说出函数用途是“限制高频触发函数的执行频率”。
2、闭包与定时器机制(占 30%)
✅ 解释 timer 闭包保存状态和 clearTimeout 的重置逻辑。
3、应用场景举例(占 20%)
✅ 至少给出两个合理场景(如搜索框、resize)。
4、附加细节(占 10%)
✅ 提及 apply 的上下文绑定作用。
✅ 对比节流函数(throttle)的差异。

如果候选人能结合代码实现细节和实际业务场景作答,即可判定为满分回答。

2-1、闭包(Closure)原理

闭包是 函数与其词法作用域(lexical scope)的组合,使得内部函数可以访问外部函数的变量,即使外部函数已执行完毕。其本质是 函数在定义时捕获并保留了其所在作用域的引用
实现机制
1、词法环境(Lexical Environment)
函数在定义时记录其所在作用域的变量引用,形成闭包链。
2、垃圾回收豁免
被闭包引用的变量不会被回收,即使外部函数已销毁。
3、私有性
通过闭包可以实现变量隐藏(类似私有变量)。
自增ID生成器实现
代码实现

function createIdGenerator(initialId = 0) {let id = initialId; // 通过闭包保留id状态return function() {return ++id; // 每次调用自增};
}// 使用示例
const generator = createIdGenerator();
console.log(generator()); // 1
console.log(generator()); // 2 

关键特性

特性说明
状态持久化通过闭包保存id变量状态
隔离性每次调用工厂函数生成独立计数器
可定制初始值支持传入initialId参数

postscript:
闭包原理得分点
1、作用域链描述
(30%)
✅ 解释函数定义时捕获外部作用域变量的机制

2、生命周期控制(30%)
✅ 说明闭包如何阻止变量被垃圾回收

3、实际应用场景(20%)
✅ 结合ID生成器案例说明状态保持

4、延伸扩展(20%)
✅ 提及闭包在模块化/私有变量中的应用
ID生成器得分点

评分项满分扣分点示例
闭包正确使用4未使用闭包(直接返回全局变量)
自增逻辑正确3后置递增(id++)导致从0开始
支持多实例独立2多个生成器共享同一计数器
参数可配置性1未实现initialid参数

进阶追问示例
1、如何实现ID重置功能?

function createIdGenerator() {let id = 0;return {next: () => ++id,reset: () => id = 0};
}

2、多个生成器之间如何避免冲突?
每个生成器通过独立闭包隔离状态,天然线程安全。
通过闭包实现的状态管理是前端高频考点,建议结合内存管理(如闭包泄露场景)深化理解。

3-1、手写Promise.all实现,并处理错误情况的代码及详细解释:
function myPromiseAll(promises) {return new Promise((resolve, reject) => {// 检查输入是否为可迭代对象if (typeof promises?.[Symbol.iterator] !== 'function') {reject(new TypeError('Argument is not iterable'));return;}const promiseArray = Array.from(promises);const results = new Array(promiseArray.length);let completedCount = 0;let hasRejected = false;// 处理空数组的情况if (promiseArray.length === 0) {resolve(results);return;}for (let i = 0; i < promiseArray.length; i++) {// 将每个元素转为 PromisePromise.resolve(promiseArray[i]).then((result) => {if (hasRejected) return; // 已失败则忽略results[i] = result; // 按索引存储结果completedCount++;// 全部完成时 resolveif (completedCount === promiseArray.length) {resolve(results);}}).catch((error) => {if (!hasRejected) {hasRejected = true;reject(error); // 首个错误直接 reject}});}});
}

核心实现要点
1、类型检查

  • 使用Symbol.iterator 验证输入是否为可迭代对象(如数组)。
  • 非可迭代对象直接reject类型错误。
    2、边界处理
  • 空数组直接resolve([])。
  • 非Promise值通过 Promise.resolve()包装。
    3、状态管理
  • results 数组按索引存储结果,保证输出顺序。
  • completedCount 计数器跟踪完成数量。
  • hasRejected标志位确保只reject一次。
    4、错误处理
  • 任何一个Promise失败立即终止,后续结果被忽略。
  • 通过hasRejected防止多次调用reject

使用示例

// 成功场景
myPromiseAll([Promise.resolve(1),Promise.resolve(2)
]).then(console.log); // 输出: [1, 2]// 失败场景
myPromiseAll([Promise.resolve(1),Promise.reject('error')
]).catch(console.log); // 输出: 'error'// 非 Promise 值
myPromiseAll([1, 2, 3]).then(console.log); // 输出: [1, 2, 3]// 空数组
myPromiseAll([]).then(console.log); // 输出: []

与原生的差异对比

特性原生Promise.all手写实现
错误处理立即终止完全一致
非Promise值自动包装为Promise通过Promise.resolve实现
结果顺序严格按输入顺序完全一致
可迭代对象支持支持通过类型检查实现

得分点解析

得分项分值扣分点示例
正确返回Promise实例2未返回Promise对象
处理可迭代对象2未校验输入类型导致奔溃
结果顺序保留3使用push()导致顺序错乱
错误立即终止3未处理多个reject调用
非Promise值兼容2未使用Promise.resolve包装
空数组处理1未特殊处理空数组场景

通过以上实现,完整复现了 Promise.all 的核心功能,并严格处理了边界条件和异常场景。

4 Proxy实现对象属性访问监控

基础实现

function createObservedObject(target) {const handler = {get(target, property, receiver) {console.log(`[监控] 读取属性 ${property}`);// 递归代理嵌套对象const value = Reflect.get(target, property, receiver);return typeof value === 'object' && value !== null ? createObservedObject(value) // 深度代理: value;},set(target, property, value, receiver) {console.log(`[监控] 设置属性 ${property} = ${value}`);return Reflect.set(target, property, value, receiver);}};return new Proxy(target, handler);
}// 使用示例
const user = createObservedObject({name: 'Alice',address: {city: 'Beijing'},scores: [90, 85]
});console.log(user.name); // 输出监控日志
console.log(user.address.city); // 触发嵌套对象监控
user.scores.push(95); // 监控数组操作

核心机制
1、属性读取监控

  • get陷阱:拦截所有属性访问,包括嵌套对象
  • 递归代理:对对象/数组类型属性值进行深度代理
  • Reflect转发:保持原对象的默认行为
    2、属性修改监控
  • set陷阱:拦截所有属性赋值操作
  • 数组方法拦截push/pop等操作会触发get + set
    进阶优化版本
function createDeepProxy(target, cache = new WeakMap()) {// 防止重复代理和循环引用if (cache.has(target)) return cache.get(target);const handler = {get(target, prop) {console.log(`Read ${prop}`);const value = Reflect.get(...arguments);// 自动代理对象/数组/Set/Map等引用类型if (typeof value === 'object' && value !== null) {return createDeepProxy(value, cache);}return value;},set(target, prop, value) {console.log(`Set ${prop} to`, value);return Reflect.set(...arguments);}};const proxy = new Proxy(target, handler);cache.set(target, proxy); // 缓存已代理对象return proxy;
}

关键特性对比

特性基础版本优化版本
循环引用处理❌ 会栈溢出✅ WeakMap 缓存解决
复合数据类型支持对象/数组对象/数组/Set/Map
性能优化❌ 重复创建代理✅ 缓存机制
监控范围直接属性访问包括原型链方法调用

应用场景
1、数据变更追踪

  • Vue3响应式系统的核心实现原理
  • 实现自动化的表单数据校验

2、调试工具

  • 实时监控对象状态变化
  • 记录属性访问历史

3、权限控制

  • 禁止访问私有属性(属性名前带)
get(target, prop) {if (prop.startsWith('_')) {throw new Error('私有属性禁止访问');}return Reflect.get(...arguments);
}

4、性能分析

  • 统计热点属性访问频率
  • 检测内存泄漏(长时间未被访问的属性)

注意事项
1、Proxy局限性

  • 无法监控Object.keys()等静态方法
  • JSON.stringfy()无效

2、性能影响

  • 深度代理大型对象时会有内存开销
  • 生产环境建议选择性代理关键数据

3、浏览器兼容性

  • IE不支持Proxy, 需要用polyfill如 proxy-polyfill

面试得分点
1、基础实现
(40%)

  • 正确使用Proxy的 get/set 陷阱
  • 处理基本数据类型和引用类型差异

2、深度代理(30%)

  • 递归代理嵌套对象
  • 处理数组等特殊对象

3、异常处理(20%)

  • 循环引用解决方案
  • 私有属性访问控制

4、扩展认知(10%)

  • 能够关联到Vue3响应式原理
  • 提出实际应用场景

通过Proxy实现的属性监控是前端高级开发的必备技能,建议结合具体框架源码(如Vue3 的 reactive模块)深入理解。

5、Event Loop核心机制

JavaScript 是单线程语言,通过 **事件循环(Event Loop)**处理异步操作。其运行机制分为以下层级:

层级内容优先级
调用栈同步代码执行(后进先出)最高
微任务Promise.then、MutationObserver
宏任务setTimeout、setInterval、I / O

执行规则:
1、同步代码立即执行,清空调用栈
2、执行所有微任务(直到微任务队列为空)
3、执行一个宏任务
4、重复步骤2-3
题目代码分析

console.log(1);
setTimeout(() => console.log(2), 0);
Promise.resolve().then(() => console.log(3));
console.log(4);

执行步骤分解
1、同步阶段

  • console.log(1)—> 输出1
  • setTimeout 回调注册到宏任务队列
  • Promise.then回调注册到微任务队列
  • console.log(4)—>输出4
    此时输出:1 —> 4

2、微任务阶段:

  • 检查微任务队列,执行()=>console.log(3)——> 输出3
    此时输出:1 —> 4 —> 3

3、宏任务阶段:

  • 取出第一个宏任务(SetTimeout回调),执行()=>console.log(2)—>输出2

最终输出:1—> 4 —> 3 —> 2
关键原理图示

[调用栈]1. 执行 console.log(1)
2. 将 setTimeout 回调加入宏任务队列
3. 将 Promise.then 回调加入微任务队列
4. 执行 console.log(4)[微任务队列]
↓ 执行所有微任务 → console.log(3)[宏任务队列]
↓ 执行一个宏任务 → console.log(2)

常见误区
1、零延迟不代表立即执行
setTimeout(fn, 0)的实质是最快 4ms (浏览器规范限制)后加入宏任务队列,而非立即执行。
2、微任务优先级碾压宏任务
即使宏任务进入队列,也必须等待当前所有微任务执行完毕。
3、嵌套任务的影响
若在微任务中创建新的微任务,会持续执行直到队列清空:

Promise.resolve().then(() => {console.log(3);Promise.resolve().then(() => console.log(5)); // 新增微任务
});

输出顺序为:1 —>4 —> 3 —> 5—>2
面试得分点

考察维度满分回答要点
阶段划分明确同步/微任务/宏任务执行顺序
队列机制解释微任务队列清空后才执行宏任务
API分类正确区分宏任务与微任务API
浏览器差异提及Node.js与浏览器的差异

掌握 Event Loop机制是前端核心能力,建议通过 Loupe 可视化工具加深理解。

二、Vue架构深度

1、Vue3响应式原理(对比Vue2)

Vue2使用Object.defineProperty递归遍历对象属性实现响应式,存在无法检测新增属性和数组下标变化的问题。Vue3改用Proxy代理对象,可监听动态属性增减和更多操作类型(如delete)。同时引入Reflect操作对象,配合effect-tracker实现更精准的依赖收集。组件实例层面通过Composition API实现逻辑复用,相比Vue2的Options API更灵活

postScript:
得分点:

  • 准确对比两代实现差异(3分)
  • 指出Proxy优势(2分)
  • 说明Composition API作用(2分)
  • 提及Refleck使用(1分)
2、Vue自定义拖拽指令

核心逻辑
1、事件驱动:通过 mousedown 触发拖拽, mousemove 更新位置,mouseup 结束拖拽
2、坐标计算:基于 clientx / clientv 计算鼠标相对元素的偏移量
3、边界处理:可选限制元素在可视区域内移动((如搜索结果[7]的弹窗拖拽实现))

// 注册全局指令(可放入单独文件)
Vue.directive('drag',  {inserted(el, binding) {// 设置元素定位方式(需确保元素可定位)el.style.position  = 'absolute';// 获取拖拽触发区域(默认整个元素可拖拽)const dragHandle = binding.value?.handle  ? el.querySelector(binding.value.handle)  : el;dragHandle.style.cursor  = 'move';let startX = 0, startY = 0, initialLeft = 0, initialTop = 0;// 鼠标按下事件 const onMouseDown = (e) => {e.preventDefault(); // 记录初始位置 startX = e.clientX; startY = e.clientY; initialLeft = el.offsetLeft; initialTop = el.offsetTop; document.addEventListener('mousemove',  onMouseMove);document.addEventListener('mouseup',  onMouseUp);};// 鼠标移动事件 const onMouseMove = (e) => {const dx = e.clientX  - startX;const dy = e.clientY  - startY;// 计算新位置 let newLeft = initialLeft + dx;let newTop = initialTop + dy;// 边界限制(可选)if (binding.value?.boundary)  {newLeft = Math.max(0,  Math.min(newLeft,  window.innerWidth  - el.offsetWidth)); newTop = Math.max(0,  Math.min(newTop,  window.innerHeight  - el.offsetHeight)); }// 更新元素位置 el.style.left  = `${newLeft}px`;el.style.top  = `${newTop}px`;};// 鼠标松开事件 const onMouseUp = () => {document.removeEventListener('mousemove',  onMouseMove);document.removeEventListener('mouseup',  onMouseUp);};// 绑定事件 dragHandle.addEventListener('mousedown',  onMouseDown);// 保存引用用于解绑 el.__vueDragHandler__ = onMouseDown;},unbind(el) {// 移除事件监听 const dragHandle = el.__vueDragHandler__?.currentTarget || el;dragHandle.removeEventListener('mousedown',  el.__vueDragHandler__);}
});

示例代码解说

关键优化点
  • 定位方式自动检测:强制设置position: absolute避免用户未设置 [参考2] 、 [参考3]
  • 事件解绑机制:在unbind阶段移除监听防止内存泄漏
  • 性能优化:使用requestAnimationFrame优化高频触发(示例未展示,可自行扩展)
  • 触摸屏支持:添加touchstart/touchmove事件实现移动端适配
实现效果对比
功能特性本方案实现参考方案[7]实现
基础拖拽✔️✔️
边界限制✔️✔️
拖拽手柄✔️✔️
移动端支持
嵌套滚动处理
扩展建议
  • 组合API:可结合useDraggable组合式API封装(Vue3特性)
  • 拖拽回调:通过指令参数暴露@drag-start/@drag-end事件
  • 拖拽限制:支持自定义边界检测函数
3、如何设计高性能的动态表单渲染组件?

(1) 分层架构设计

graph TD
A[Schema解析层] --> B[组件映射层]
B --> C[状态管理层]
C --> D[渲染引擎层]
D --> E[扩展插件层]
  • Schema解析层:支持JSON Schema/自定义DSL描述表单结构
  • 组件映射层:建立字段类型与组件映射关系
  • 状态管理层:原子化状态管理 + 响应式更新
  • 渲染引擎层:虚拟滚动 + 差异对比渲染
  • 扩展插件层:校验、联动、条件渲染等能力扩展

(2)核心性能优化手段
1)虚拟滚动实现

// 滚动容器
<VirtualScroll itemHeight={80} visibleCount={10}total={1000}
>{(index) => <FormField schema={schemaList[index]}/>}
</VirtualScroll>
  • 仅渲染可视区域内的表单项
  • 滚动时动态计算渲染位置
  • 支持预估高度和动态高度调整

2)状态管理优化

// 使用Recoil实现原子化状态
const fieldState = atom({key: 'formField',default: null,effects: [persistState] // 持久化副作用
});// 组件内按需订阅
const [value, setValue] = useRecoilState(fieldState(id));

3)差异更新算法

function diffUpdate(oldSchema, newSchema) {const patches = [];// 使用JSON-Patch算法生成差异jsonDiff.compare(oldSchema, newSchema, patches);applyPatches(patches); // 局部更新DOM
}

(3)渲染引擎实现
1)组件级缓存

// Vue 实现示例
<template><component :is="getComponent(schema.type)":schema="schema":key="schema.id + schema.version" // 版本控制缓存v-memo="[schema.version]"/>
</template>

2)异步分块渲染

// 使用requestIdleCallback分批次渲染
function renderChunk(schemas) {let index = 0;function doChunk() {if (index >= schemas.length) return;// 每次渲染50个项const chunk = schemas.slice(index, index + 50);renderItems(chunk);index += 50;requestIdleCallback(doChunk);}doChunk();
}

(4)性能指标与优化验证
性能测试标准

指标目标值测量工具
首次内容渲染(FCP)<1sLighthouse
输入响应延迟<50msChrome DevTools
内存占用<100MB/千字段Chrome Memories面板
滚动帧率>=60fpsChrome Rendering面板

优化前后对比

gantt
title 千字段表单性能优化对比
dateFormat  X
axisFormat %s
section 优化前
渲染耗时 : 0, 2500
内存占用 : 0, 350
section 优化后
渲染耗时 : 0, 300
内存占用 : 0, 80

(5)扩展能力设计
1、动态加载策略

// Web Worker 加载复杂校验规则
const worker = new Worker('validator.worker.js');
worker.postMessage({ rule, value });
worker.onmessage = (e) => updateValidation(e.data);

2、GPU加速渲染

.form-item {will-change: transform, opacity;transform: translateZ(0);
}

3、服务端渲染降级方案

// 服务端生成静态结构
app.use('/form', (req, res) => {const html = renderToString(<StaticForm schema={schema} />);res.send(html);
});

(六)最佳实践建议
1、Schema设计规范:

  • 字段ID保持稳定
  • 避免深层嵌套结构
  • 版本化字段配置

2、性能兜底方案:

// 监控渲染时长自动降级
let startTime = Date.now();
renderForm();
if (Date.now() - startTime > 1000) {showLoading();enableDegradedMode(); // 启用简化渲染模式
}

3、开发者工具集成:

// 表单性能分析插件
FormDevTools.register({trackRender: true,highlightUpdates: true
});

通过以上架构设计和优化策略,可实现支持万级字段的动态表单流畅渲染,同时保持开发体验和可维护性。建议结合具体框架特性进行适配实现,并持续进行性能分析和迭代优化。

4、解释Vue组件间通信的5种方式及适用场景

1. Props / $emit(父子组件通信)
实现方式:

  • 父 → 子:通过 props 传递数据
  • 子 → 父:通过 $emit 触发事件
<!-- Parent.vue -->
<Child :title="parentTitle" @update="handleUpdate"/><!-- Child.vue -->
<button @click="$emit('update', newValue)">提交</button>

适用场景:

  • 简单的父子组件数据传递
  • 层级不超过3层的组件通信
    优点:Vue官方推荐方式,类型检查支持完善
    缺点:跨层级通信需要逐层传递(Prop drilling)

2. Event Bus(全局事件总线)
实现方式

// eventBus.js
import Vue from 'vue';
export const EventBus = new Vue();// ComponentA.vue
EventBus.$emit('data-change', payload);// ComponentB.vue
EventBus.$on('data-change', callback);

适用场景:

  • 非父子组件间通信(如兄弟组件)
  • 小型项目快速实现跨组件通信
    优点:轻量级、快速实现解耦
    缺点:事件管理混乱,难以维护大型项目
    3. Vuex/Pinia(状态管理)
    实现方式:
// store.js
export default new Vuex.Store({state: { count: 0 },mutations: { increment(state) { state.count++ } }
});// Component.vue
this.$store.commit('increment');

适用场景:

  • 中大型项目全局状态管理
  • 需要持久化/可追溯的状态
  • 多个组件共享复杂业务逻辑
    优点:集中管理、时间旅行调试
    缺点:小型项目引入会增加复杂度

4. provide / inject(依赖注入)
实现方式:

// 祖先组件
export default {provide() {return { theme: this.themeData };}
}// 后代组件
export default {inject: ['theme']
}

适用场景:

  • 跨多层级组件传递数据(如主题/配置)
  • 高阶组件(HOC)开发
    优点:避免逐层传递
    缺点:数据流向不透明,破坏组件独立性

5、attrs / listeners(透传属性和事件)
实现方式:

<!-- 中间组件 -->
<GrandChild v-bind="$attrs" v-on="$listeners"/><!-- 最终组件 -->
<template><div>{{ $attrs.title }}</div>
</template>

适用场景:

  • 创建高阶包装组件
  • 透传第三方组件原生事件和属性
    优点:避免手动声明每个 prop/event
    缺点:Vue3 中 $listeners 被合并到 $attrs

通信方式选型矩阵

场景推荐方案典型示例
直接父子通信Props+$emit表单控件双向绑定
兄弟组件通信Event Bus / Vuex购物车商品数量同步
跨多层级组件provide/inject主题切换 / 权限注入
复杂状态共享Vuex / Pinia用户登录状态全局管理
高阶组件开发attrs / listeners封装第三方UI库组件

性能优化要点
1、避免滥用全局状态
Pinia/Vuex的状态变更会触发所有相关组件更新,需合理划分模块
2、使用计算属性缓存

computed: {filteredList() { /* 复杂计算 */ }
}

3、事件总线及时销毁

beforeDestroy() {EventBus.$off('event-name');
}

Vue3 新增特性
1、Composition API 响应式传递

const sharedState = reactive({ count: 0 });
provide('state', sharedState);

2、Teleport 跨 DOM 通信

<teleport to="#modal-container"><Dialog/>
</teleport>

根据项目规模和组件关系选择合适的通信方式,避免出现「过度设计」或「通信混乱」两种极端。对于超过 5 层组件嵌套的场景,建议优先考虑状态管理方案。

5、如何用Composition API重构 Options API的复杂组件?

**一、重构步骤
1、组件结构分析
**原始Options API结构示例:

export default {data() {return { count: 0,user: null,loading: false}},computed: {doubleCount() { return this.count * 2 }},methods: {async fetchUser() {this.loading = true;this.user = await api.getUser();this.loading = false;}},mounted() {this.fetchUser();}
}

2. 核心逻辑拆分
按功能模块拆分为组合式函数:

// useCounter.js
export function useCounter(initial = 0) {const count = ref(initial);const doubleCount = computed(() => count.value * 2);return { count, doubleCount };
}// useUser.js
export function useUser() {const user = ref(null);const loading = ref(false);async function fetchUser() {loading.value = true;user.value = await api.getUser();loading.value = false;}onMounted(fetchUser);return { user, loading, fetchUser };
}

3.整合到Setup函数

<script setup>
import { useCounter, useUser } from './composables';const { count, doubleCount } = useCounter();
const { user, loading } = useUser();
</script>

二、关键重构技巧
1、响应式数据转换

Options APIComposition API
data ()ref()/ reactive()
this.property.value访问
computedcomputed()
watchwatch()/ watchEffect()

2、生命周期映射

Options APIComposition API
beforeCreate无对应,直接写在setup
created无对应,直接写在setup
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted

3、方法处理优化

// Options API
methods: {handleClick() { /* ... */ }
}// Composition API
const handleClick = () => { /* ... */ };

三、复杂场景重构示例
1、混合状态与副作用

原代码:

export default {data() {return { scrollY: 0 }},mounted() {window.addEventListener('scroll', this.handleScroll);},methods: {handleScroll() {this.scrollY = window.scrollY;}},beforeUnmount() {window.removeEventListener('scroll', this.handleScroll);}
}

重构后:

// useScroll.js
export function useScroll() {const scrollY = ref(0);const handleScroll = () => {scrollY.value = window.scrollY;};onMounted(() => window.addEventListener('scroll', handleScroll));onUnmounted(() => window.removeEventListener('scroll', handleScroll));return { scrollY };
}

2、跨组件逻辑复用
原代码:

// 多个组件重复相同代码
export default {data() {return { darkMode: false }},methods: {toggleTheme() {this.darkMode = !this.darkMode;document.body.classList.toggle('dark', this.darkMode);}}
}

重构为可复用逻辑:

// useTheme.js
export function useTheme() {const darkMode = ref(false);const toggleTheme = () => {darkMode.value = !darkMode.value;document.body.classList.toggle('dark', darkMode.value);};return { darkMode, toggleTheme };
}// 组件中使用
const { darkMode, toggleTheme } = useTheme();

四、重构收益对比

指标Options APIComposition API
代码行数120行80行(减少33%)
功能模块复用率0%60%逻辑可复用
代码可读性逻辑分散在不同选项按功能集中组织
TypeScript支持有限完整类型推断
Tree-shaking无法优化未使用选项按需导入组合式函数

五、最佳实践建议
1、渐进式重构策略

  • 优先重构500行以上的复杂组件
  • 使用<script setup>语法糖简化代码
  • 保留Options API用于简单组件
    2、组合式函数设计规范
// 命名规范:use+功能名称
function usePagination() {}// 单一职责:每个函数只处理一个关注点
function useDataFetching() {}
function useFormValidation() {}// 明确输入输出:参数类型化,返回响应式对象
function useSearch(params: SearchParams) {return { results, loading };
}

3、性能优化技巧

// 使用 shallowRef 优化大对象
const bigData = shallowRef({ /* 大型数据集 */ });// 使用 markRaw 跳过代理
const staticConfig = markRaw({ version: 3 });// 合理使用 watchEffect 自动依赖收集
watchEffect(() => {console.log(count.value);
});

通过以上方法,可系统性地将复杂的 Options API 组件改造为更模块化、更易维护的 Composition API 组件。建议结合 Vue DevTools 的 Composition API 调试功能进行验证。

三、工程化与性能优化

1、Webpack构建速度优化方案(至少5种)

一、缓存加速方案
1、持久化缓存(Webpack5+)

// webpack.config.js
module.exports = {cache: {type: 'filesystem', // 使用文件系统缓存buildDependencies: {config: [__filename] // 配置文件变更时自动失效缓存}}
};

原理:

  • 将模块解析、代码生成结果缓存到磁盘
  • 二次构建时直接复用缓存内容
    效果:冷启动构建速度提升60% ~ 80%

二、范围缩小策略
2、精准文件搜索

resolve: {modules: ['node_modules'], // 指定模块查找目录extensions: ['.js', '.vue'], /

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/895776.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对称加密算法——IDEA加密算法

Java IDEA算法详解 1. 理论背景 IDEA&#xff08;International Data Encryption Algorithm&#xff09;是一种对称密钥加密算法&#xff0c;由Xuejia Lai和James Massey于1991年提出。它被设计用于替代DES&#xff08;Data Encryption Standard&#xff09;算法&#xff0c;…

rustdesk远程桌面自建服务器

首先&#xff0c;我这里用到的是阿里云服务器 centos7版本&#xff0c;win版客户端。 准备工作 centos7 服务器端文件&#xff1a; https://github.com/rustdesk/rustdesk-server/releases/download/1.1.11-1/rustdesk-server-linux-amd64.zip win版客户端安装包&#xff1…

【DL】浅谈深度学习中的知识蒸馏 | 输出层知识蒸馏

目录 一 核心概念与背景 二 输出层知识蒸馏 1 教师模型训练 2 软标签生成&#xff08;Soft Targets&#xff09; 3 学生模型训练 三 扩展 1 有效性分析 2 关键影响因素 3 变体 一 核心概念与背景 知识蒸馏&#xff08;Knowledge Distillation, KD&#xff09;是一种模…

嵌入式学习第十六天--stdio(二)

文件打开 open函数 #include <fcntl.h> int open(const char *pathname&#xff0c;int flags); int open(const char *pathname&#xff0c;int flags&#xff0c;mode_t mode); 功能: 打开或创建文件 参数: pathname //打开的文件名 flags //操作…

对话智面创始人陶然:一是初心和心态,二是坚持和心力

随着经济全球化的加深和市场竞争的日益激烈&#xff0c;企业迅速发展成为了每一个企业家的梦想。然而&#xff0c;要实现企业的快速发展并保持竞争力&#xff0c;企业战略的人力资源管理起着至关重要的作用。 企业的核心竞争力是“人才”的竞争&#xff0c;无论是研发、销售、…

mybatis使用typeHandler实现类型转换

使用mybatis作为操作数据库的orm框架&#xff0c;操作基本数据类型时可以通过内置的类型处理器完成java数据类型和数据库类型的转换&#xff0c;但是对于扩展的数据类型要实现与数据库类型的转换就需要自定义类型转换器完成&#xff0c;比如某个实体类型存储到数据库&#xff0…

Qt开发①Qt的概念+发展+优点+应用+使用

目录 1. Qt的概念和发展 1.1 Qt的概念 1.2 Qt 的发展史&#xff1a; 1.3 Qt 的版本 2. Qt 的优点和应用 2.1 Qt 的优点&#xff1a; 2.2 Qt 的应用场景 2.3 Qt 的应用案例 3. 搭建 Qt 开发环境 3.1 Qt 的开发工具 3.2 Qt SDK 的下载和安装 3.3 Qt 环境变量配置和使…

王炸 用AI+飞书 分解 一键生成 项目计划表模版

效果图&#xff1a; 各字段设置&#xff1a; 以下是一个使用 AI&#xff08;DeepSeeker&#xff09; 飞书多维表格分解项目待办模板的示例&#xff0c;你可以根据实际情况进行调整和优化&#xff1a; 列表中需要选择对象&#xff0c;且选择输出结果&#xff08;记得控制字符长度…

从月牙定理看古希腊数学的奇妙突破

文章目录 每日一句正能量前言古希腊人的 “化圆为方” 之梦&#xff08;一&#xff09;几何作图的基本规则&#xff08;二&#xff09;化圆为方问题的起源与发展&#xff08;三&#xff09;化圆为方的意义 月牙面积定理的诞生&#xff08;一&#xff09;希波克拉底的生平与成就…

实战:vLLM多机多卡部署大模型

两台服务器 1. Docker容器中使用GPU 必须确保已安装并配置 NVIDIA Docker。你可以安装 nvidia-docker 来确保 GPU 驱动能够被 Docker 使用 #安装 nvidia-docker&#xff1a; sudo apt-get install nvidia-docker2#然后重启 Docker&#xff1a; sudo systemctl restart docke…

Win10环境使用零讯ZeroNews内网穿透实现Deepseek对外服务

Win10环境使用零讯ZeroNews内网穿透实现Deepseek对外服务 前言 之前笔者已经在Win10环境搭建好了Ollama、DeepSeek、Open WebUI、Dify等组件&#xff0c;成功实现了私有化部署及内网访问&#xff1a; https://lizhiyong.blog.csdn.net/article/details/145505686 https://l…

halcon 条形码、二维码识别、opencv识别

一、条形码 函数介绍 create_bar_code_model * 1.创建条码读取器的模板 * 参数一&#xff1a;通用参数的名称&#xff0c;针对条形码模型进行调整。默认值为空 * 参数二&#xff1a;针对条形码模型进行调整 * 参数三&#xff1a;条形码模型的句柄。 create_bar_code_model (…

【学习资源】时间序列数据分析方法(2)-mWDN和AutoEncoder

接着上次的【学习资源】时间序列数据分析方法&#xff08;1&#xff09;-CSDN博客&#xff0c;本次介绍mWDN和AutoEncoder 解决时序数据分类的方法。介绍模型原理、应用场景和参考代码。也从模型性能、训练效率、模型复杂度、计算复杂度、可解释性、适应性和泛化能力、健壮性、…

【TI C2000】F28002x的系统延时、GPIO配置及SCI(UART)串口发送、接收

【TI C2000】F28002x的系统延时、GPIO配置及SCI&#xff08;UART&#xff09;串口发送、接收 文章目录 系统延时GPIO配置GPIO输出SCI配置SCI发送、接收测试附录&#xff1a;F28002x开发板上手、环境配置、烧录及TMS320F280025C模板工程建立F28002x叙述烧录SDK库文件说明工程建…

亲测有效!使用Ollama本地部署DeepSeekR1模型,指定目录安装并实现可视化聊天与接口调用

文章目录 一、引言二、准备工作&#xff08;Ollama 工具介绍与下载&#xff09;2.1 Ollama介绍2.2 Ollama安装 三、指定目录安装 DeepSeek R1四、Chatbox 可视化聊天搭建4.1 Chatbox下载安装4.2 关联 DeepSeek R1 与 Chatbox 的步骤 五、使用 Ollama 调用 DeepSeek 接口5.1 请求…

Python 面向对象的三大特征

前言&#xff1a;本篇讲解面向对象的三大特征&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;&#xff0c;还有比较细致的&#xff08;类属性类方法&#xff0c;静态方法&#xff09;&#xff0c;分步骤讲解&#xff0c;比较适合理清楚三大特征的思路 面向对象的…

Jmeter如何计算TPS

1.在jmeter中计算出接口请求的个数 1175 1172 1172 174 200 416 384 1174 5867 2.计算接口平均响应时间 计算每个接口的请求次数乘以平均响应时间&#xff0c;所有接口相加&#xff0c;然后除以所有接口的数量总和&#xff0c;得到接口的平均响应时间 (1175*18191172*…

docker push镜像到阿里云

阿里云账号 阿里云-计算&#xff0c;为了无法计算的价值 开通个人镜像容器 进入控制台&#xff0c;试用容器 实例列表界面 点击上图中的个人&#xff0c;个人版特性 创建个人版&#xff1a; 个人版实例界面&#xff1a; 设置密码 个人版实例&#xff1a; 创建镜像仓库 如上…

大模型与智能体:螺旋共生,绘就智能新蓝图

大模型与智能体&#xff1a;螺旋共生&#xff0c;绘就智能新蓝图 在人工智能的前沿领域&#xff0c;大模型与智能体宛如两颗璀璨的星辰&#xff0c;以一种精妙的螺旋共生关系&#xff0c;重塑着智能世界的格局&#xff0c;深刻影响着我们生活与工作的方方面面。 大模型&#x…

第2章 信息技术发展(一)

2.1 信息技术及其发展 2.1.1 计算机软硬件 计算机硬件(Computer Hardware)是指计算机系统中由电子、机械和光电元件等组成的各种物理装置的总称。 计算机软件 (Computer Software)是指计算机系统中的程序及其文档&#xff0c;程序是计算任务的处理对象和处理规则的描述; 文档…