Vue3学习历程杂记(1)
1. 浏览器调试技巧
1.1 调试工具使用
-
语雀文档参考:Vue3 官方调试文档
-
语雀文档参考:Vue3 官方调试文档
链接作用:该链接指向 Vue.js 官方文档的「工具」章节,专门介绍 Vue DevTools 浏览器扩展的使用。点击后可以:- 了解如何安装 Vue DevTools 浏览器扩展
- 学习使用 DevTools 检查组件树、状态、事件
- 掌握性能分析和时间旅行调试等高级功能
- 查看官方推荐的调试最佳实践
-
Watch 监视功能:在浏览器开发者工具的右侧 Watch 面板中,可以手动添加要监视的变量,实时查看其值的变化。这在调试
props和ref时特别有用。
n/img_convert/05f0455cb7d4c0404fbabaec71bff1fd.png)
2. Vue3 SFC (.vue) 单文件三大模块
2.1 <template> 模板(HTML 结构层)
作用:编写页面的 DOM 结构。
包含内容:
- HTML 标签
- Vue 指令(
v-if、v-for、v-bind、@click等) - 插值表达式
{{ 变量 }}
特点:
- Vue 编译器会将模板编译成
render()渲染函数,最终生成虚拟 DOM 并渲染为真实页面 - 不能直接编写 JavaScript 逻辑,只能通过绑定关联
<script>中定义的数据和方法 - Vue3 支持
<template>根节点多标签(无需外层包裹div)
2.2 <script> 脚本(逻辑、数据层)
作用:定义页面的所有业务逻辑、数据、方法、生命周期、props、导入组件等。
两种写法:
- Options API:传统的配置式写法
- Composition API(Setup 语法糖):组合式写法
包含内容:
- 定义响应式数据(
ref/reactive) - 定义函数方法
- 接收父组件传值
props - 定义组件自定义事件
emits - 生命周期钩子(
onMounted、onUpdated等) - 引入子组件和第三方工具
注意:在 setup 语法糖下,代码会在组件创建阶段优先执行。
2.3 <style> 样式(CSS 层)
作用:编写当前组件的样式。
三种模式:
- 普通样式:全局样式,不加
scoped会污染全页面 <style scoped>:样式只作用于当前组件 DOM(通过data-v哈希属性隔离)<style lang="scss">:可使用 Sass/Less 等 CSS 预处理器
特点:只负责样式,不参与组件逻辑与渲染。
3. .vue 文件编译与执行顺序
打包编译顺序
<script> → <template> → <style>
浏览器运行渲染顺序
<script> 先执行 → 生成 render 函数 → <template> 渲染 DOM → <style> 生效
完整分步流程
第一步:优先解析执行 <script>
- 代码从上到下执行
- 导入依赖 → 执行
setup/ 选项配置 → 创建响应式数据、声明方法 - 组件实例创建、数据初始化全部在这一步完成
第二步:编译 <template>
- 模板不会原样留在页面
- Vue 编译器把
template编译成render渲染函数 render函数内部使用<script>里定义的数据生成 VNode(虚拟 DOM)
第三步:挂载渲染 DOM
- 执行
render()函数 - 虚拟 DOM 转为真实 DOM,页面 HTML 渲染出来
第四步:加载 <style>
- CSS 样式载入页面
- DOM 应用对应样式

cn/img_convert/6755a962e6cab421fb5693e5c74b22f2.png)

核心原理
- 模板里
ref="变量名"→ 必须在<script setup>顶层作用域存在同名ref变量 - 组件挂载
onMounted后,Vue 自动把真实 DOM 对象赋值给oracleDiv.value
错误分析
错误原因:ref() 创建变量是在点击函数运行时才创建,但 DOM 在 onMounted(页面初始化时)就已经渲染完毕。
执行流程分析:
- script 运行阶段:只定义
getDivContent函数,let oracleDiv = ref()这行代码完全没运行,变量不存在 - DOM 挂载阶段:Vue 找全局名叫
oracleDiv的ref变量,找不到!无法赋值 DOM - 用户点击后:才临时在函数局部创建
oracleDiv,此时挂载早已结束,Vue 不会回头再赋值 →value永远为null
5. Vue3 两种代码写法
5.1 Options API(选项式 API)
结构:固定配置选项
<script>
export default {
// 数据
data() {
return {
num: 0,
user: { name: '小李', age: 18 }
}
},
// 方法
methods: {
add() {
this.num++
}
},
// 生命周期
mounted() {
console.log('页面挂载完毕')
},
// watch 监听
watch: {
num(newV) {
console.log('num变了', newV)
},
user: {
handler() {
console.log('user变化')
},
deep: true
}
}
}
</script>
注意事项:
- 通过
this访问数据和方法:this.num/this.user data()必须返回对象
export default {
data() {
// data 必须 return 对象,页面才能拿到数据
return {
count: 0
}
}
}
- 老式组合式
setup()需要return
export default {
setup() {
const count = ref(0)
// 不在 script setup 语法糖里,想在模板中使用 → 必须 return
return { count }
}
}
5.2 组合式 API(Composition API)
<script setup>
import { ref, reactive, watch, onMounted } from 'vue'
const num = ref(0)
const user = reactive({ name: '小李', age: 18 })
const add = () => num.value++
watch(num, () => {})
onMounted(() => {})
</script>
特点:
- 相关业务代码写在一起,没有
this - 便于代码抽离封装成 hooks,大项目维护方便
6. watch 监听器详解
6.1 基本特性
- 原生
watch本身不分「增、删、改、加、减」,只要值变化就触发回调
6.2 监听对象、数组(引用值)
不写 deep: true:内部属性改动不会触发 watch
加 deep: true:对象任意层级改动、新增 key、删除 key、数组 push/pop,全部统一触发回调
const user = reactive({ name: '小明', age: 18 })
// deep:true 开启深度监听
watch(user, (newVal, oldVal) => {
console.log('对象变化了')
}, { deep: true })
user.age = 20 // 修改属性 → 触发
user.sex = '男' // 新增属性 → 触发
delete user.name // 删除属性 → 触发
6.3 监视 reactive 定义的引用数据类型
基础用法:直接监听整个 reactive 对象,不用手动 deep: true
const obj = reactive({ name: '张三', info: { age: 18 } })
// 监听整个 reactive 对象,默认自动开启 deep
watch(obj, (newVal, oldVal) => {
// newVal === oldVal → true!同一个 Proxy 地址
console.log(newVal === oldVal)
})
// 改一级属性
obj.name = '李四'
// 改深层属性
obj.info.age = 20
只监听对象里某个属性(函数写法)
watch(() => obj.name, (newV, oldV) => {
// new ≠ old,普通值,地址不一样
})
obj.name = '李四'
7. 历史来源小科普
语法糖这个词是 1960 年代 Lisp 语言发明者提出,沿用至今
箭头函数 () => {} 是普通 function 的语法糖
<script setup>遵循这个命名惯例,写法简化、逻辑不变 → 语法糖
8. 核心知识点图解

8.1 RefImpl 和 Proxy
Proxy**:管理对象内部细节改动(reactive 全靠它)
- RefImpl:
ref专属外壳,解决基本类型无法被Proxy代理的短板,.value靠它实现响应式 - 控制台显示:浏览器控制台显示
RefImpl,就是提醒你:该变量是ref包装对象,不能直接操作原始数据,JS 取值必须加.value
8.2 : 与 v-bind: 简写
| 写法 | 含义 | 传递内容 |
|---|---|---|
personList="persons"(无冒号) |
纯字符串字面量 | 子组件拿到字符串 "persons" |
:personList="persons"(带冒号) |
JS 表达式 | 把父组件 persons**变量(整个响应式数组)**传给子组件 personList |
8.3 父传子 ref 数据传递注意事项
ref 数据通过 props 传递时会自动剥除 RefImpl,子组件拿到的是原生 Proxy 数据,所以 props 有解构陷阱:
// ❌ 错误解构,丢失响应式
const { personList } = defineProps<{ personList: Item[] }>()
// ✅ 正确:用 toRefs 保持响应式
const props = defineProps<{ personList: Item[] }>()
const { personList } = toRefs(props)
9. {{ name }} 插值表达式(模板语法)
<!-- Child.vue -->
{{ name }}
作用:把 name 变量里的数据显示在网页上。
特性:
- 里面可以写简单运算:
{{ name + '666' }}→zhangsan666 - 只有模板能用
{{}},<script>里必须写props.name
更多推荐

所有评论(0)