Vue3 知识点总结 · 2026-03-20
本次共识别 13 个知识点,覆盖 7 个分类。
📂 提取来源(共 8 个文件,点击展开)
| 文件路径 | 识别到的知识点 |
|---|---|
src/views/commentAnalysis/components/period_detail/index.vue |
script setup, ref(), computed(), v-model, v-if / v-else, v-for, v-slot / #slot |
src/views/commentAnalysis/components/period_detail/pick_list_modal/index.vue |
script setup, ref(), computed(), v-if / v-else, v-for, watch(), defineProps(), defineEmits() |
src/views/commentAnalysis/components/period_overall/index.vue |
script setup |
src/views/commentAnalysis/components/period_overall/overall_section/index.vue |
script setup, ref(), computed(), v-model, v-for, v-slot / #slot, onMounted(), onUnmounted(), nextTick() |
src/views/commentAnalysis/components/period_overall/sku_section/index.vue |
script setup, ref(), v-slot / #slot, watch(), onMounted(), onUnmounted(), nextTick() |
src/views/commentAnalysis/components/period_overall/trend_section/index.vue |
script setup, ref(), v-slot / #slot, watch(), onMounted(), onUnmounted(), nextTick() |
src/views/commentAnalysis/index.vue |
script setup |
src/views/makeVideo/components/header/index.vue |
script setup, ref(), computed(), v-model, v-for, v-slot / #slot |
目录
- [🚀 Vue3 基础](#🚀 Vue3 基础)
- [⚡ 响应式 API](#⚡ 响应式 API)
- [🎯 模板指令](#🎯 模板指令)
- [👁️ 侦听器](#👁️ 侦听器)
- [📡 组件通信](#📡 组件通信)
- [🔌 生命周期](#🔌 生命周期)
- [🔧 工具函数](#🔧 工具函数)
🚀 Vue3 基础
script setup
项目中的用法 (来自 src/views/commentAnalysis/components/period_detail/index.vue、src/views/commentAnalysis/components/period_detail/pick_list_modal/index.vue、src/views/commentAnalysis/components/period_overall/index.vue、src/views/commentAnalysis/components/period_overall/overall_section/index.vue、src/views/commentAnalysis/components/period_overall/sku_section/index.vue、src/views/commentAnalysis/components/period_overall/trend_section/index.vue、src/views/commentAnalysis/index.vue、src/views/makeVideo/components/header/index.vue):
vue
</template>
<script setup>
import { h } from "vue"
import { DownOutlined } from "@ant-design/icons-vue"
import handler from "@/views/commentAnalysis/handler"
import PickListModal from "./pick_list_modal/index.vue"
const needModalOpen = ref(false)
const skuModalOpen = ref(false)
是什么: 组合式 API 语法糖,顶层变量/函数自动暴露给模板,无需 return。
面试 Q&A:
Q:Vue2 Options API 和 Vue3 Composition API 有什么区别?
A:Options API 按选项类型组织代码(data/methods/computed),逻辑分散;Composition API 按功能聚合,逻辑复用靠 composable 函数,更适合大型项目。
Q:setup() 和 <script setup> 有什么不同?
A:setup() 是函数,需要手动 return 暴露给模板;<script setup> 是编译器语法糖,顶层声明自动暴露,代码更简洁,性能略优(编译阶段优化)。
⚡ 响应式 API
ref()
项目中的用法 (来自 src/views/commentAnalysis/components/period_detail/index.vue、src/views/commentAnalysis/components/period_detail/pick_list_modal/index.vue、src/views/commentAnalysis/components/period_overall/overall_section/index.vue、src/views/commentAnalysis/components/period_overall/sku_section/index.vue、src/views/commentAnalysis/components/period_overall/trend_section/index.vue、src/views/makeVideo/components/header/index.vue):
vue
import PickListModal from "./pick_list_modal/index.vue"
const needModalOpen = ref(false)
const skuModalOpen = ref(false)
const crowdModalOpen = ref(false)
const sceneModalOpen = ref(false)
const emotionModalOpen = ref(false)
const committedNeedIds = ref([])
const committedSkuIds = ref([])
是什么: 将基本类型包装为响应式对象,JS 中访问要加 .value,模板中自动解包。
面试 Q&A:
Q:ref 和 reactive 的区别?
A:ref 用于基本类型(内部用 RefImpl 包装),访问需 .value;reactive 用于对象/数组(基于 Proxy),直接访问属性。ref 也可包对象,内部会自动调用 reactive。
Q:模板里为什么不用写 .value?
A:模板编译时会自动对 ref 解包,访问 ref.value 的操作由编译器插入,开发者无感知。
computed()
项目中的用法 (来自 src/views/commentAnalysis/components/period_detail/index.vue、src/views/commentAnalysis/components/period_detail/pick_list_modal/index.vue、src/views/commentAnalysis/components/period_overall/overall_section/index.vue、src/views/makeVideo/components/header/index.vue):
vue
]
const filteredRows = computed(() => {
let rows = handler.detailRows
for (const [rowKey, idsRef] of filterChains) {
if (!idsRef.value.length) continue
rows = rows.filter((row) =>
row[rowKey]?.some((id) => idsRef.value.includes(id))
)
}
是什么: 基于响应式数据派生的缓存值,依赖不变时不重新计算。
面试 Q&A:
Q:computed 和 methods 的区别?
A:computed 有缓存,依赖不变则直接返回缓存值,适合计算量大的场景;methods 每次调用都重新执行,适合需要触发副作用的操作。
Q:如何实现可写的 computed?
A:传入包含 get 和 set 的对象:computed({ get: () => x.value, set: v => x.value = v }),set 中手动更新源数据。
🎯 模板指令
v-model
项目中的用法 (来自 src/views/commentAnalysis/components/period_detail/index.vue、src/views/commentAnalysis/components/period_overall/overall_section/index.vue、src/views/makeVideo/components/header/index.vue):
vue
<div class="card_inner_title">评价明细</div>
<PickListModal
v-model:open="needModalOpen"
title="查找需求"
:width="440"
:anchor="pickAnchor"
:options="handler.needFilterOptions"
:selected-ids="committedNeedIds"
@confirm="onPickNeedConfirm"
>
是什么: 双向绑定语法糖,等价于 :modelValue + @update:modelValue。
面试 Q&A:
Q:v-model 的实现原理?
A:编译器将 v-model 展开为 :modelValue='val' 和 @update:modelValue='val=$event'。组件内用 defineProps(['modelValue']) + defineEmits(['update:modelValue']) 配合使用。
Q:Vue3 和 Vue2 的 v-model 有什么变化?
A:Vue2 用 :value + @input,修改靠 .sync;Vue3 统一为 :modelValue + @update:modelValue,支持多个 v-model(v-model:title、v-model:content),去掉了 .sync。
v-if / v-else
出现在: src/views/commentAnalysis/components/period_detail/index.vue、src/views/commentAnalysis/components/period_detail/pick_list_modal/index.vue
是什么: 条件渲染,false 时节点从 DOM 移除并销毁组件,适合不频繁切换的场景。
面试 Q&A:
Q:v-if 和 v-show 如何选择?
A:频繁切换用 v-show(只改 display,开销小);初始条件为假且不常切换用 v-if(减少初始渲染开销)。v-if 切换时组件会销毁重建,触发完整生命周期。
Q:v-if 和 v-for 的优先级?
A:Vue3 中 v-if 优先级高于 v-for(Vue2 相反)。不建议同时使用,应用 template 包裹 v-for,在内部元素上用 v-if,或用 computed 过滤数据。
v-for
项目中的用法 (来自 src/views/commentAnalysis/components/period_detail/index.vue、src/views/commentAnalysis/components/period_detail/pick_list_modal/index.vue、src/views/commentAnalysis/components/period_overall/overall_section/index.vue、src/views/makeVideo/components/header/index.vue):
vue
<template v-else-if="column.key === 'sku'">
<div class="sku_cell">
<template v-for="(p, i) in record.skuParts" :key="i">
<span :class="{ strike: p.strike }">{{ p.text }}</span>
<br v-if="i < record.skuParts.length - 1" />
</template>
</div>
</template>
<template v-else-if="column.key === 'needs'">
<div class="tags_cell">
是什么: 列表渲染,必须加 :key(唯一且稳定),key 用于 Diff 算法复用节点。
面试 Q&A:
Q:为什么 v-for 必须加 key?key 用 index 有什么问题?
A:key 让 Diff 算法识别节点身份,复用 DOM 减少操作。用 index 做 key 在列表增删时会导致错误复用(节点身份和数据不匹配),造成状态错乱,应用数据唯一 ID。
Q:Vue3 的 Diff 算法有什么优化?
A:Vue3 Diff 引入最长递增子序列(LIS)算法,最小化节点移动次数;同时增加静态标记(patchFlag)跳过静态节点对比,比 Vue2 快 1.3~2 倍。
v-slot / #slot
出现在: src/views/commentAnalysis/components/period_detail/index.vue、src/views/commentAnalysis/components/period_overall/overall_section/index.vue、src/views/commentAnalysis/components/period_overall/sku_section/index.vue、src/views/commentAnalysis/components/period_overall/trend_section/index.vue、src/views/makeVideo/components/header/index.vue
是什么: 插槽内容分发,支持默认插槽、具名插槽、作用域插槽。
面试 Q&A:
Q:默认、具名、作用域插槽的区别?
A:默认插槽:<slot> 接收未命名内容;具名插槽:<slot name='header'> + <template #header> 指定位置;作用域插槽:<slot :data='item'> + <template #default='{ data }'> 让父组件拿到子组件数据。
👁️ 侦听器
watch()
项目中的用法 (来自 src/views/commentAnalysis/components/period_detail/pick_list_modal/index.vue、src/views/commentAnalysis/components/period_overall/sku_section/index.vue、src/views/commentAnalysis/components/period_overall/trend_section/index.vue):
vue
})
watch(
() => props.open,
(isOpen) => {
if (isOpen) draftIds.value = props.selectedIds.slice()
}
)
// 计算药丸样式
是什么: 侦听指定数据源,变化时执行回调,可获取新旧值,支持 deep/immediate。
面试 Q&A:
Q:watch 和 watchEffect 的核心区别?
A:watch 需要明确指定侦听源,懒执行(默认不立即执行),可拿到新旧值;watchEffect 自动收集依赖,立即执行一次,拿不到旧值。
Q:watch 监听对象的某个属性怎么写?
A:用 getter 函数:watch(() => obj.key, callback)。直接写 watch(obj.key, ...) 只是监听当时的值,不是响应式的。
Q:如何停止侦听?
A:const stop = watch(...); stop() 调用返回值即可停止。组件卸载时会自动停止,手动停止用于在卸载前提前结束侦听。
📡 组件通信
defineProps()
项目中的用法 (来自 src/views/commentAnalysis/components/period_detail/pick_list_modal/index.vue):
vue
import pickHandler from "./handler"
const props = defineProps({
open: {
type: Boolean,
default: false
},
title: {
type: String,
default: ""
是什么: 声明组件接收的 props,父传子的核心方式,支持类型约束和默认值。
面试 Q&A:
Q:Vue3 有哪些组件通信方式?
A:① props/emit(父子)② v-model(双向)③ ref + defineExpose(父调子方法)④ provide/inject(跨层级)⑤ Pinia(全局状态)⑥ mitt 事件总线(任意组件)
Q:props 是单向数据流,子组件能直接修改吗?
A:不能直接修改,会报警告。正确做法:① emit 通知父组件修改 ② 将 prop 赋值给本地 ref 再修改本地数据 ③ 使用 v-model。
defineEmits()
项目中的用法 (来自 src/views/commentAnalysis/components/period_detail/pick_list_modal/index.vue):
vue
})
const emit = defineEmits(["update:open", "confirm"])
const draftIds = ref([])
const isAnchored = computed(() => !!props.anchor)
const wrapCls = computed(() =>
props.anchor ? `${props.wrapClassName} pick_list_modal_anchored` : props.wrapClassName
是什么: 声明组件可触发的自定义事件,子传父的核心方式。
面试 Q&A:
Q:emit 和 v-model 的关系?
A:v-model 本质是 :modelValue + @update:modelValue 的语法糖。子组件用 defineEmits(['update:modelValue']),然后 emit('update:modelValue', newVal) 即可实现双向绑定。
🔌 生命周期
onMounted()
项目中的用法 (来自 src/views/commentAnalysis/components/period_overall/overall_section/index.vue、src/views/commentAnalysis/components/period_overall/sku_section/index.vue、src/views/commentAnalysis/components/period_overall/trend_section/index.vue):
vue
const resizeChart = () => chart && chart.resize()
onMounted(() => {
nextTick(() => {
if (!pieRef.value) return
chart = echarts.init(pieRef.value)
chart.setOption(buildPieOption())
window.addEventListener("resize", resizeChart)
})
})
是什么: 组件挂载到真实 DOM 后执行,可安全操作 DOM、发起请求。
面试 Q&A:
Q:Vue3 生命周期和 Vue2 的对应关系?
A:beforeCreate/created → setup();beforeMount → onBeforeMount;mounted → onMounted;beforeUpdate → onBeforeUpdate;updated → onUpdated;beforeDestroy → onBeforeUnmount;destroyed → onUnmounted。
Q:为什么不在 setup 顶层直接操作 DOM?
A:setup 执行时组件还未挂载,DOM 不存在。需要在 onMounted 里操作 DOM,此时模板已渲染完毕。
onUnmounted()
项目中的用法 (来自 src/views/commentAnalysis/components/period_overall/overall_section/index.vue、src/views/commentAnalysis/components/period_overall/sku_section/index.vue、src/views/commentAnalysis/components/period_overall/trend_section/index.vue):
vue
})
onUnmounted(() => {
window.removeEventListener("resize", resizeChart)
chart?.dispose()
chart = null
})
</script>
<style lang="less" src="./index.less" scoped></style>
是什么: 组件销毁后执行,必须在此清除定时器、取消订阅,防止内存泄漏。
面试 Q&A:
Q:不清除定时器会发生什么?
A:组件销毁后定时器仍在运行,回调中访问已销毁组件的数据会报错,且定时器无法被 GC 回收,导致内存泄漏。每次重新挂载组件还会叠加创建新定时器。
🔧 工具函数
nextTick()
项目中的用法 (来自 src/views/commentAnalysis/components/period_overall/overall_section/index.vue、src/views/commentAnalysis/components/period_overall/sku_section/index.vue、src/views/commentAnalysis/components/period_overall/trend_section/index.vue):
vue
onMounted(() => {
nextTick(() => {
if (!pieRef.value) return
chart = echarts.init(pieRef.value)
chart.setOption(buildPieOption())
window.addEventListener("resize", resizeChart)
})
})
是什么: 等待下一次 DOM 更新后执行,用于数据修改后立即操作更新后的 DOM。
面试 Q&A:
Q:nextTick 的原理?
A:Vue 的 DOM 更新是异步批量的(微任务队列)。修改数据后 DOM 不会立即更新,nextTick 将回调推入同一微任务队列的末尾,等 DOM 更新完成后执行。底层用 Promise.then 实现。
Q:nextTick 和 setTimeout 的区别?
A:nextTick 用微任务(Promise),在当前宏任务结束、下一个宏任务开始前执行,时机更早;setTimeout 是宏任务,会在所有微任务执行完后才运行,时机更晚,可能看到中间状态。
由 vue_learn.py 自动生成 · 2026-03-20 13:23