作为一名大三前端学习者,在基于 Vue3 开发道路病害检测系统 的过程中,我越发觉得:框架只是工具,JS 基础才是真正的底气。
这篇文章就把我在真实项目里高频用到、又特别关键的 JS 知识点整理出来,附带实战代码和面试思路,既是复盘,也希望帮到同样在学前端的同学。
一、作用域与闭包:按钮防抖、防重复提交
在做表单提交、列表搜索、病害数据查询时,按钮很容易被重复点击,导致重复请求接口。这时候就用到防抖,底层就是闭包。
1. 知识点
- 闭包:内层函数可以访问并保留外层函数的变量
- 块级作用域:
let/const避免变量污染
2. 项目实战代码
javascript
javascript
// utils/debounce.js
export function debounce(fn, delay = 800) {
let timer = null;
return (...args) => {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
在 Vue3 组件里使用:
vue
xml
<template>
<button @click="handleQuery">查询病害数据</button>
</template>
<script setup>
import { debounce } from '@/utils/debounce';
// 数据查询防抖,避免频繁触发接口
const handleQuery = debounce(() => {
console.log('请求道路病害数据...');
// 这里调用接口获取列表数据
}, 800);
</script>
3. 面试点
闭包可能造成内存泄漏,所以在组件销毁时要清理定时器:
js
ini
import { onUnmounted } from 'vue';
onUnmounted(() => {
timer = null;
});
二、原型与原型链:全局挂载工具方法
项目里很多地方都要用到时间格式化、文件处理等工具,如果每个组件都 import 太麻烦,我会把方法全局挂载。
1. 知识点
- 实例会继承原型上的方法
- 全局挂载后,所有组件都能直接用
2. 项目实战
javascript
javascript
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import { formatDate } from '@/utils/date';
const app = createApp(App);
app.config.globalProperties.$formatDate = formatDate;
app.mount('#app');
组件里直接用:
js
ini
// 格式化病害检测时间
const time = $formatDate(item.detectTime);
3. 面试点
Vue 组件方法不要用箭头函数,因为箭头函数没有自己的 this,会拿不到组件实例。
三、Promise & async/await:接口请求必用
我的项目里大量接口请求:登录、获取病害列表、上传图片、提交结果,全都靠 Promise 和 async/await。
1. 知识点
- Promise 解决回调地狱
- async/await 让异步代码像同步一样好读
2. 项目实战
javascript
ini
// 获取病害数据(async/await 写法)
const getDiseaseList = async () => {
try {
const res = await $axios.get('/api/disease/list', {
params: { page: 1, size: 10 }
});
tableData.value = res.data;
} catch (err) {
ElMessage.error('数据加载失败');
}
};
并发请求(比如同时拿用户信息 + 统计数据):
js
csharp
const [userInfo, statistics] = await Promise.all([
$axios.get('/api/user/info'),
$axios.get('/api/disease/statistics')
]);
3. 面试点
- Promise.all:全部成功才成功,一个失败就整体失败
- async/await 代码更清晰、便于错误处理
四、事件循环 & nextTick:DOM 更新后操作
修改数据后,DOM 不会立刻更新。比如我要操作表格、图表、弹窗里的 DOM,必须用 nextTick。
1. 知识点
- 同步任务 → 微任务 → 宏任务
nextTick是微任务,在 DOM 更新后执行
2. 项目实战
vue
xml
<template>
<div ref="chartRef">{{ data }}</div>
</template>
<script setup>
import { ref, nextTick } from 'vue';
const data = ref('');
const chartRef = ref(null);
const updateData = async () => {
data.value = '新数据';
// 此时 DOM 还没更
await nextTick();
// 现在可以安全操作 DOM 或初始化图表
console.log(chartRef.value);
};
</script>
3. 面试题(必背)
js
scss
console.log(1)
setTimeout(()=>console.log(2),0)
Promise.resolve().then(()=>console.log(3))
nextTick(()=>console.log(4))
输出顺序:1 → 3 → 4 → 2
五、深浅拷贝:避免改坏原数据
在做病害信息编辑弹窗时,我需要把一行数据复制到表单里。如果直接赋值,改表单会同步改列表,这就必须深拷贝。
1. 知识点
- 浅拷贝:只拷贝第一层,引用类型共用地址
- 深拷贝:完全独立,修改不影响原对象
2. 项目实战代码
javascript
javascript
// utils/clone.js
export function deepClone(obj, map = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj;
if (map.has(obj)) return map.get(obj);
const res = Array.isArray(obj) ? [] : {};
map.set(obj, res);
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
res[key] = deepClone(obj[key], map);
}
}
return res;
}
使用:
js
csharp
// 编辑数据时深拷贝,防止污染原列表
const formData = ref(deepClone(row));
3. 面试点
Vue 响应式是基于引用类型的,不做深拷贝会出现 "牵一发而动全身" 的 BUG。
总结
这段时间做 Vue3 项目我最大的感受:
- 防抖、接口请求、数据处理、DOM 操作,全是 JS 基础
- 框架用得越熟练,越能体会到 JS 核心的重要性
- 把项目里的知识点整理成博客,既是巩固,也是面试素材
后面我会继续更新 Vue3 项目实战、前端面试题、项目踩坑、工程化 相关内容,欢迎关注~