Repository navigation
Expand file tree
/
Copy path前端进阶
More file actions
413 lines (263 loc) · 10.2 KB
/
Copy path前端进阶
File metadata and controls
413 lines (263 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
https://chat.deepseek.com/share/j8nyst8bdgu21arts8
Promise/Async async/await 是什么,解决了什么,注意事项是什么?
async/await 是 Promise 的语法糖,让异步代码写起来像同步代码。错误处理推荐使用 try-catch,但要注意 try-catch 只能捕获 await 所在的错误,未 await 的 Promise 或回调中的错误仍需 .catch。
同时要避免在循环中滥用 await 导致性能问题,可以用 Promise.all 并发执行。
开始Vue 3项目
↓
选择构建工具(Vite)
↓
项目初始化 + 安装核心依赖
├── Vue 3
├── Vue Router (SPA需要)
├── Pinia (状态管理)
└── Tailwind CSS
↓
配置Tailwind (tailwind.config.js)
↓
组件开发流程:
1. 创建.vue单文件组件
2. 使用<script setup>语法糖 https://chat.deepseek.com/share/1vlgnq1ef0srk5ek48
3. 定义响应式数据(ref/reactive)
4. 计算属性(computed)和侦听器(watch)
5. 生命周期钩子(onMounted等)
6. 模板编写(结合Tailwind类)
7. 样式作用域(scoped或CSS模块)
↓
路由配置(如需)
↓
状态管理设计(如需)
↓
优化与打包
<script setup>语法糖{
与普通 <script> 的区别:无需 export default,顶层变量自动暴露。
无法定义 name 选项(可通过额外 <script> 或 vite-plugin-vue 解决)。
不支持 inheritAttrs、components 等选项,需使用 defineOptions 或普通 <script> 配合。
编译器宏的使用:
defineProps:声明 props,支持运行时声明和纯类型声明。
defineEmits:声明可触发的事件。
defineExpose:暴露组件内部属性/方法给父组件的模板 ref。
defineOptions(Vue 3.3+):定义组件名、inheritAttrs 等。
这些宏无需手动导入,编译时自动处理。
响应式 API 的使用:ref、reactive、computed、watch 等用法与普通 setup() 完全一致。
注意 ref 在模板中自动解包,但在函数中需 .value。
组件递归 / 动态组件: 递归组件需要显式指定 name(使用 defineOptions 或第二个 <script>)。
动态组件 <component :is="Component"> 直接传入组件对象即可。
生命周期钩子:可直接调用 onMounted、onUpdated 等,无需写在 setup() 内部。
与 TypeScript 的结合
defineProps<{ msg: string }>() 实现纯类型声明。
从 vue 导入 PropType 用于复杂类型。
编译时优化原理
模板中的变量引用被静态提升,减少运行时代理。
编译后的代码比普通 setup() 更简洁高效。
}
浏览器原生功能:
1 输入框聚焦了,父元素也该有反应。
用focus-within
2 对于没网络了情况,页面应该怎么办?
浏览器最基础能力windows.addEventListener("offline")
windows.addEventListener("online")
3 不重要的任务慢慢跑:
function showMessage(){
console.log(" ran when browser was idle");
}
if("requstIdleCallback" in window){
requstIdleCallback(showMessage)
}
适合:分析埋点,可以延迟的非关键任务,后台数据整理,琐碎工作。
4 如何让组件根据自身容器尺寸来响应,而不是盯着整个屏幕视口?
用container query。如:@用container (min-width:400px)
5 唯一id 用const bytes=new Uint8Array(8);
crypto.getRandomValues(bytes);
const uniqueID=Array.from(bytes).map(b=>b.toString(16).padStart(2,"0")).join("");
6 别一做弹窗就装modal库。
简单用<dialog>.
它自带了对话框行为,焦点管理更自然,可访问性更好,背景区域会失活,ESC可关闭,不必靠一堆css,js拼出来。
组合式API对比选项API ?
https://chat.deepseek.com/share/ax5600ycq181ccngtq
为什么组合式 API 更优?
对比维度 选项式 API 组合式 API
逻辑聚合 一个功能的代码(data/methods/mounted)散落在各处 ; 所有相关代码(状态、方法、生命周期)写在一起,内聚性强
逻辑复用 需要 mixins,存在命名冲突、隐式依赖等问题 ; 封装成普通函数(useFetch),在任何组件中直接调用,清晰且无副作用
TypeScript 支持 this 上下文类型推导困难 ; 普通变量和函数,类型推断完美
代码组织 文件变大后难以维护(上千行 options 混乱) ;按功能拆分多个 useXXX 函数,每个函数职责单一
Tree Shaking 未使用的生命周期/选项无法被摇掉; 只导入用到的 API(ref、onMounted),打包更小
CSS3 关键特性
css
复制
/* Flex布局 */
.container {
display: flex;
justify-content: center; /* 主轴对齐 */
align-items: center; /* 交叉轴对齐 */
flex-wrap: wrap; /* 换行 */
}
/* Grid布局 */
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1rem;
}
/* CSS变量 */
:root {
--primary-color: #3b82f6;
--spacing: 1rem;
}
.element {
color: var(--primary-color);
margin: var(--spacing);
}
ref 和 reactive 有什么区别?
A:
ref:
javascript
const count = ref(0) // 包装基本类型
count.value = 1 // 访问需要 .value
// 在模板中自动解包:{{ count }}
reactive:
const state = reactive({ count: 0 }) // 包装对象
state.count = 1 // 直接访问
// 重新赋值会丢失响应性
Q3:什么时候用 ref,什么时候用 reactive?
A:
基本类型、DOM引用 → ref
复杂对象、嵌套结构 → reactive
函数返回响应式数据 → 统一用 ref(避免解构丢失响应性)
对比。async await 比Promise链 更好?
https://chat.deepseek.com/share/84zehc5e5mu2ucbo5t
优势对比
维度 Promise 链 (.then/.catch) async/await
可读性 链式调用,多步骤时缩进层级深,逻辑易分散; 同步写法,线性流程,更接近人类思维
错误处理 需在链尾统一 .catch(),或每个 .then() 里单独捕获,易遗漏; 标准 try-catch,与同步代码一致,更直观
调试 断点难以追踪 .then() 内部的异步堆栈; await 行可直接打断点,调用栈更清晰
条件/循环 需要递归或 Promise 构造器配合,容易出错; 直接使用 if/while/for,自然流畅
中间值传递 需层层嵌套或通过外部变量保存; 普通变量赋值即可
async/await 的缺点(何时 Promise 链更好)
简单单次异步:.then() 更简洁
js
fetch(url).then(res => res.json()).then(data => console.log(data))
// vs
const res = await fetch(url)
const data = await res.json()
console.log(data)
并发任务:Promise.all + async/await 仍需组合 Promise 方法
js
// 正确做法
const [user, products] = await Promise.all([getUser(), getProducts()])
// 错误做法(串行)
const user = await getUser()
const products = await getProducts() // 等待 user 返回后才请求,性能差
如果开发者不了解并发控制,容易写出低效的串行代码。而 Promise 链天然鼓励用 Promise.all。
需要在非 async 函数中(如顶级作用域、事件监听):要么立即执行 async 函数,要么用 .then()。
JavaScript 高频考点
Q17:let、const、var 的区别?
A:
特性
var
let
const
作用域
函数作用域
块级作用域
块级作用域
变量提升
提升并初始化undefined
提升但不初始化
提升但不初始化
重复声明
允许
不允许
不允许
暂时性死区
无
有
有
推荐程度
不推荐
推荐
最推荐
Q18:箭头函数和普通函数的区别?
A:
this 绑定:箭头函数没有自己的 this,继承外层
arguments 对象:箭头函数没有 arguments
构造函数:箭头函数不能作为构造函数
原型属性:箭头函数没有 prototype
yield 关键字:箭头函数不能用作 Generator
Q19:Event Loop 输出顺序题
javascript
下载
复制
console.log(1)
setTimeout(() => console.log(2), 0)
Promise.resolve().then(() => console.log(3))
console.log(4)
// 输出:1, 4, 3, 2
// 解析:同步 → 微任务 → 宏任务
5.3 CSS/Tailwind 高频考点
Q20:Flexbox 和 Grid 如何选择?
A:
Flexbox:一维布局(行或列)
css
复制
/* 适合:导航栏、卡片列表、对齐元素 */
.container {
display: flex;
justify-content: space-between; /* 主轴 */
align-items: center; /* 交叉轴 */
}
Grid:二维布局(行和列)
css
复制
/* 适合:整体页面布局、复杂网格 */
.container {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-template-rows: auto 1fr auto;
gap: 1rem;
}
Q21:CSS 选择器优先级计算规则?
A:
优先级(从高到低):
!important(避免使用)
行内样式 style="color: red"
ID 选择器 #id
类/属性/伪类 .class, [type="text"], :hover
元素/伪元素 div, ::before
通配/继承 *, 继承样式
计算规则:(A, B, C, D)
A: 行内样式个数
B: ID 选择器个数
C: 类/伪类/属性个数
D: 元素/伪元素个数
比较时从A到D依次比较
🎯 六、实战最佳实践总结
6.1 项目结构规范
复制
src/
├── assets/ # 静态资源
├── components/ # 公共组件
│ ├── common/ # 全局通用组件
│ └── layout/ # 布局组件
├── composables/ # 组合式函数
├── stores/ # Pinia状态管理
├── router/ # 路由配置
├── views/ # 页面组件
├── utils/ # 工具函数
├── styles/ # 全局样式
├── types/ # TypeScript类型
└── main.ts # 入口文件
6.2 性能优化清单
组件懒加载:路由和组件按需加载
图片优化:WebP格式、懒加载、CDN
代码分割:利用Vite/Rollup的代码分割
Tree-shaking:移除未使用代码
Gzip/Brotli压缩:服务器配置
缓存策略:合理的Cache-Control
第三方库按需引入:如lodash-es
虚拟滚动:长列表优化
6.3 常见错误与解决方案
响应式丢失:使用 toRefs解构reactive对象
内存泄漏:及时清理定时器、事件监听器
重复渲染:合理使用 v-memo、computed缓存
样式冲突:使用CSS Modules或Scoped样式
TypeScript类型错误:正确定义组件Props类型
这个深度解析涵盖了现代前端开发的核心概念、高频考点和最佳实践。掌握这些知识点,不仅能提高开发效率,也能在面试中展现扎实的技术功底。建议结合实际项目,深入理解每个概念的应用场景。