Vue3 基础知识点整理 —— 从入门到响应式核心完全指南

文章目录

  • [一、Vue 整体介绍](#一、Vue 整体介绍)
  • [二、Vue3 Hello World 四步流程](#二、Vue3 Hello World 四步流程)
  • [三、setup 入口函数](#三、setup 入口函数)
    • [插值语法(声明式渲染 / 胡子语法)](#插值语法(声明式渲染 / 胡子语法))
  • 四、响应式核心概念
  • [五、reactive 响应式 API](#五、reactive 响应式 API)
  • [六、ref 响应式 API](#六、ref 响应式 API)
  • [七、reactive vs ref 选型方案](#七、reactive vs ref 选型方案)
  • 全文总结
  • 核心知识点复盘
  • [常见问题 / 避坑指南](#常见问题 / 避坑指南)

本文基于 Vue3 组合式 API(Composition API),从零开始梳理 Vue3 的核心概念与响应式原理,配合可运行的代码示例,适合前端新手入门及有经验的开发者快速复盘。


一、Vue 整体介绍

Vue (读音 /vjuː/,同 view)是一套用于构建用户界面渐进式 JavaScript 框架。拆解这三个关键词,就能理解 Vue 的本质定位:

关键词 含义 通俗理解
构建用户界面 基于数据生成 HTML 标签结构,配合 CSS 样式,渲染出用户可见的 UI Vue 的核心工作就是"把数据变成页面"
渐进式 可以循序渐进地学习,学多少用多少,不强求一次性掌握全部 就像搭积木,你可以只用一块,也可以搭出城堡
框架 提供一套固定的语法规则,开发时必须遵循 Vue 的既定规范 在 Vue 的地盘,就得按 Vue 的规矩来写代码

渐进式的两层含义:

① 局部改造 ------ 轻量嵌入现有项目

你有一个老旧的 jQuery 项目,不想全部重写,只想把某个复杂的表单模块改成响应式的。没问题------直接在页面中引入一个 Vue 的 CDN 脚本,就能在局部区域使用 Vue 的功能。

html 复制代码
<!-- 仅需一行 script 引入,即可在现有项目中局部使用 Vue -->
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

② 整站开发 ------ 完整的现代化技术栈

当你需要从零搭建一个完整的中大型 Web 应用时,Vue 生态提供了全套解决方案:

复制代码
Vue3(核心框架)+ VueRouter(路由)+ Pinia(状态管理)+ Vite(工程化构建)+ 模块化开发

重点 :"Vue 的渐进式是什么意思",核心回答就是------可以自底向上逐层应用。简单页面只用核心库,复杂应用再引入路由、状态管理等生态工具,不强制全量使用。


二、Vue3 Hello World 四步流程

从一个最简示例入手,理解 Vue3 应用从零到渲染的完整过程。以下代码可以在浏览器中直接打开运行。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue3 Hello World</title>
</head>
<body>
    <!-- 第1步:引入 Vue3 源代码(CDN 方式) -->
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

    <!-- 第2步:准备 HTML 挂载容器 -->
    <div id="app">
        <!-- 第4步:使用插值语法渲染数据 -->
        <h1>{{ msg }}</h1>
        <p>我是 {{ obj.name }},今年 {{ obj.age }} 岁</p>
        <p>{{ obj.age >= 18 ? '成年了' : '未成年' }}</p>
        <p>来年就 {{ obj.age + 1 }} 岁了</p>
        <p>fn 的返回值 = {{ fn() }}</p>
        <p>{{ msg }} 由 {{ msg.split(' ').length }} 个单词组成</p>
    </div>

    <script>
        // 第3步:创建 Vue 应用实例并定义业务数据
        Vue.createApp({
            setup() {
                const msg = 'hello world'
                const obj = {
                    name: '张三',
                    age: 9
                }
                const fn = () => {
                    return 666
                }
                // setup 中声明的数据必须 return 才能被模板使用
                return { msg, obj, fn }
            }
        }).mount('#app')  // 把内容挂载到 id="app" 的容器里
    </script>
</body>
</html>

四步流程拆解:

步骤 操作 关键代码 说明
1. 引入 Vue 加载 Vue3 核心库 <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> 本地文件或 CDN 均可,引入后全局可用 Vue 对象
2. 准备容器 定义挂载点 <div id="app">...</div> Vue 只控制该容器内的 DOM,容器外不受影响
3. 创建实例 调用 createApp 并配置 setup Vue.createApp({ setup() { ... } }) setup 是组合式 API 的入口,数据和方法都在这里定义
4. 渲染数据 使用插值语法 {``{ }} {``{ msg }} 将 JS 表达式的结果渲染到 HTML 标签内部

思考题 :如果页面上有两个 <div>,一个 id="app",一个 id="root",只有 #app 内的 {``{ msg }} 会被解析------因为 mount('#app') 指定了挂载目标,Vue 只管理它挂载的那个容器。


三、setup 入口函数

setupVue3 专属 的组合式 API 入口函数,所有组合式 API 的代码都在 setup 函数内部编写,可以把它理解为整个组件的"逻辑中枢"。

核心规则:

规则 说明
变量/方法必须声明在 setup 内 模板中用到的数据、函数,都必须在 setup 中定义
必须 return 暴露出去 只有 return 出去的数据,模板才能访问到
setup 内的 this 不是 Vue 实例 与 Vue2 的 Options API 完全不同,setup不使用 this 关键字

典型结构:

javascript 复制代码
Vue.createApp({
    setup() {
        // 1. 在这里定义数据
        const message = 'Hello'

        // 2. 在这里定义方法
        const sayHi = () => {
            console.log('Hi')
        }

        // 3. 必须 return 出去,模板才能用
        return {
            message,
            sayHi
        }
    }
}).mount('#app')

插值语法(声明式渲染 / 胡子语法)

语法{``{ JS表达式 }}

作用:将表达式的运算结果渲染到 HTML 标签的内部文本中。

合法的表达式类型

类型 示例 渲染结果
变量 {``{ msg }} hello world
字面常量 {``{ 100 }} 100
对象属性取值 {``{ obj.name }} 张三
三元运算 {``{ obj.age >= 18 ? '成年' : '未成年' }} 未成年
算术运算 {``{ obj.age + 1 }} 10
函数/方法调用 {``{ fn() }} 666
组合表达式 {``{ msg.split(' ').length }} 2

⚠️ 注意{``{ }} 中只能写单一 JS 表达式 ,不能写 if/for/while 等语句块。表达式必须有返回值,if 语句没有返回值,所以不能在插值中使用。


四、响应式核心概念

在 Vue 的响应式体系中,有三个关键角色:

复制代码
┌──────────┐      修改数据       ┌──────────────┐      自动更新       ┌──────────┐
│   数据    │ ──────────────────▶ │  响应式系统   │ ──────────────────▶ │   视图   │
│ (state)  │                     │ (Reactivity) │                     │  (View)  │
└──────────┘                     └──────────────┘                     └──────────┘
     ▲                                                                    │
     └──────────────────── 用户交互(事件)────────────────────────────────┘
角色 定义 在代码中的体现
数据 setup 函数中 return 返回的变量和方法 const msg = ref('hello')
视图 HTML 页面的 DOM 标签 <div id="app">...</div> 内的内容
数据响应式 数据变化后,页面视图自动同步更新 修改 msg.value,页面无需手动刷新

Vue 的核心思想:数据驱动视图 ------ 开发者只需关注数据的变化,Vue 自动完成 DOM 更新,彻底告别手动 document.querySelector + innerHTML 的时代。

对比传统做法 vs Vue 做法

javascript 复制代码
// ❌ 传统做法:手动操作 DOM(不仅繁琐,而且容易出错)
document.querySelector('#name').innerHTML = '新名字'

// ✅ Vue 做法:只修改数据,视图自动更新
obj.name = '新名字'  // 页面自动变化,无需操作 DOM

⚠️ 关键陷阱:普通变量不具备响应式

这是 Vue3 新手最容易踩的坑。在 setup 中直接声明的普通变量,修改后页面不会更新

javascript 复制代码
setup() {
    // ❌ 这样声明的变量没有响应式 ------ 改了数据,页面纹丝不动!
    let count = 0
    const add = () => {
        count++  // 数据确实变了,但页面不会更新
    }
    return { count, add }
}

原因 :Vue 的响应式依赖 JavaScript 的 ProxyObject.defineProperty 来拦截数据的读取和修改,普通变量不具备这种拦截能力。必须使用 reactiveref 这两个 API 来包裹数据,才能让 Vue "感知"到数据的变化。


五、reactive 响应式 API

reactive 用于将对象类型 的数据转换为响应式代理对象,底层基于 ES6 的 Proxy 实现。

特性 说明
作用 让对象/数组类型数据具备响应式
参数限制 只能传入对象或数组,不能传字符串、数字等基础类型
返回值 返回一个 Proxy 代理对象,用法和原对象完全一致

传基本数据类型:

完整代码示例

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue3 reactive 示例</title>
</head>
<body>
    <div id="app">
        <p>我叫 {{ obj.name }},今年 {{ obj.age }} 岁</p>
    </div>

    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <script>
        // 第1步:从 Vue 中解构导入 reactive
        const { createApp, reactive } = Vue

        createApp({
            setup() {
                // 第2步:传入对象,生成响应式代理对象
                // ✅ reactive 的参数必须是对象/数组
                const obj = reactive({
                    name: '张三',
                    age: 18
                })

                // ❌ 基础类型会报警告,且不具备响应式
                // const num = reactive(100)  // 不要这样做!

                // 第3步:return 暴露出去
                return { obj }
            }
        }).mount('#app')
    </script>
</body>
</html>

代码思路解析:

  1. 从 Vue 中解构导入const { createApp, reactive } = Vue,这是 ES6 的解构赋值写法。
  2. 包裹对象reactive({ name: '张三', age: 18 }) 返回一个响应式代理对象 obj
  3. 验证响应效果 :在浏览器控制台中,直接输入 obj.name = '李四',你会发现页面上的名字立刻自动更新------这就是响应式的威力。

reactive 的限制:

javascript 复制代码
// ❌ 不能用于基础类型 ------ 这是 reactive 最大的限制
const count = reactive(0)       // 报错或无效
const name = reactive('hello')  // 报错或无效
const flag = reactive(true)     // 报错或无效

// ✅ 只能用于对象/数组
const user = reactive({ name: 'Tom', age: 20 })   // 正确
const list = reactive([1, 2, 3])                   // 正确

底层原理补充reactive 底层使用 Proxy 代理整个对象。基础类型(数字、字符串等)在 JS 中是按值传递的,Proxy 无法代理一个"值",只能代理一个"对象引用"。所以 reactive 天然无法处理基础类型------这也是为什么需要 ref 的原因。


六、ref 响应式 API

ref 是比 reactive 适用范围更广的响应式 API,既能处理基础类型,也能处理引用类型。

特性 说明
作用 生成响应式数据,全类型兼容
基础类型支持 ✅ 数字、字符串、布尔值
引用类型支持 ✅ 对象、数组(内部自动调用 reactive
访问方式 模板中直接使用,JS 中需 .value

完整代码示例

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue3 ref 示例</title>
</head>
<body>
    <div id="app">
        <!-- 模板中使用:直接写变量名,无需 .value -->
        <p>{{ mes }}</p>
        <p>我叫 {{ obj.name }},今年 {{ obj.age }} 岁了</p>
        <button @click="onClick">修改 ref 数据</button>
    </div>

    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <script>
        // 第1步:从 Vue 中解构导入 ref
        const { createApp, ref } = Vue

        createApp({
            setup() {
                // 第2步:传入任意类型数据,生成响应式包装对象
                // ref 定义基础类型 ------ 字符串
                const mes = ref('hello world')

                // ref 定义引用类型 ------ 对象
                const obj = ref({
                    name: '小vue',
                    age: 9
                })

                // 定义点击事件,修改 ref 数据
                const onClick = () => {
                    // 第3步:JS 中修改/取值必须通过 .value
                    mes.value = '你好世界'

                    // 修改 ref 包裹的对象属性
                    obj.value.name = 'Vue3'
                    obj.value.age = 10
                }

                return { mes, obj, onClick }
            }
        }).mount('#app')
    </script>
</body>
</html>

.value 规则详解(面试高频考点):

场景 写法 说明
HTML 模板中取值 {``{ mes }} 模板自动解包,不需要 .value
HTML 模板中取对象属性 {``{ obj.name }} 对象也会自动解包,不需要 .value
JS 代码中取值 console.log(mes.value) 必须.value 访问
JS 代码中修改 mes.value = '新值' 必须.value 赋值
JS 中修改对象属性 obj.value.name = '新名字' .value 拿到对象,再 .name 修改属性

代码思路解析:

javascript 复制代码
// ref('hello world') 的内部简化结构
const mes = ref('hello world')
// mes 的本质 ≈ { value: 'hello world' }
// └── Vue 对这个对象做了响应式代理
// └── 模板中 Vue 会自动"扒开"这层壳,所以不需要 .value
// └── JS 中你必须手动"扒开",用 .value 操作

// ref 接收对象时,内部其实是转交给了 reactive
const obj = ref({ name: '小vue', age: 9 })
// 内部等价于:
// ref({ name, age }) → { value: reactive({ name, age }) }

记忆口诀 :模板自动解包不用 .value,JS 手动操作必须 .value


七、reactive vs ref 选型方案

两者对比:

对比维度 reactive ref
支持基础类型 ❌ 不支持 ✅ 支持
支持对象/数组 ✅ 支持 ✅ 支持(内部转调 reactive)
JS 中访问方式 直接使用,无 .value 必须 .value
模板中访问方式 直接使用 自动解包,直接使用
底层实现 Proxy 代理 对象包装 + Proxy(对象类型时)
解构是否保持响应式 ❌ 解构会丢失响应式 ❌ 解构也会丢失(需用 toRefs)

核心原则 :能用 reactive 就用 reactive,用不了的就用 ref

✅ 优先用 reactive 的场景 ------ 表单固定字段对象

表单的字段结构通常是预先定义好的,不会有动态新增/删除属性的需求,这是 reactive 的最佳使用场景:

javascript 复制代码
const loginForm = reactive({
    username: '',
    password: '',
    rememberMe: false
})

// 直接修改属性即可触发响应式更新
loginForm.username = 'admin'
loginForm.password = '123456'

为什么用 reactive? 表单对象的字段是固定的,不需要 .value 访问,代码更简洁直观。

✅ 使用 ref 的场景:

场景一:对象属性不确定(后端异步赋值)

javascript 复制代码
// 初值不确定,后端返回数据后再整体替换
const user = ref({})
// ... 异步请求后 ...
user.value = { name: '张三', age: 30, role: 'admin' }  // 整体替换

如果用 reactive,整体替换对象会丢失响应式引用(因为换了一个新对象);但 ref 通过 .value 赋值,Vue 能正确追踪到变化。

场景二:响应式数组

javascript 复制代码
const list = ref([])
// 后端返回列表数据后直接赋值
list.value = [1, 2, 3, 4, 5]

场景三:基础类型(数字、字符串、布尔)

javascript 复制代码
// 这没得选 ------ reactive 不支持基础类型
const count = ref(0)
const message = ref('hello')
const isLoading = ref(false)
const isVisible = ref(true)

选型决策速查:

复制代码
要定义的数据是什么类型?
│
├── 基础类型(string / number / boolean)
│   └── ✅ 只能用 ref
│
├── 数组
│   └── ✅ 推荐 ref :方便整体替换(如后端返回新数组)
│
└── 对象
    ├── 字段固定、结构明确(如表单)
    │   └── ✅ 推荐 reactive :代码简洁,无需 .value
    │
    └── 字段不确定、需整体替换(如后端异步数据)
        └── ✅ 推荐 ref :支持整体赋值

全文总结

本文从 Vue3 的最基础概念出发,按照概念 → 原理 → 实战 → 选型的递进逻辑,系统梳理了以下内容:

  1. Vue 整体定位:渐进式 JavaScript 框架,核心是"构建用户界面",可轻量嵌入也可整站开发。
  2. Hello World 四步流程:引入源码 → 准备容器 → 创建实例 → 插值渲染,这是每个 Vue3 应用的骨架。
  3. setup 入口函数:组合式 API 的起点,变量和方法都在此定义并 return 暴露。
  4. 响应式核心概念:数据驱动视图,数据变则视图自动变,Vue 的核心价值所在。
  5. reactive:面向对象/数组的响应式 API,基于 Proxy 实现,不能处理基础类型。
  6. ref :全类型兼容的响应式 API,基础类型直接包装,对象类型内部转调 reactive,JS 中访问需 .value
  7. 选型方案 :表单固定对象用 reactive,其余场景(基础类型、数组、需整体替换的对象)用 ref

核心知识点复盘

序号 知识点 一句话总结
1 Vue3 应用创建 createApp({ setup() {...} }).mount('#app')
2 setup 函数 组合式 API 入口,数据必须 return 才能被模板使用
3 插值语法 {``{ JS表达式 }},支持变量、三元、算术、函数调用等
4 响应式定义 数据变化 → 视图自动更新,Vue 的核心思想
5 reactive 仅支持对象/数组,直接访问属性,无需 .value
6 ref 全类型支持,JS 中必须 .value,模板中自动解包
7 ref 本质 ref(x) ≈ 把 x 包进 { value: x },并对其做响应式代理
8 解构陷阱 reactiveref 解构后都会丢失响应式(需 toRefs

常见问题 / 避坑指南

❓ 1. 为什么 setup 里的普通变量改了页面不更新?

javascript 复制代码
// ❌ 错误写法
let count = 0
count++  // 数据变了,页面没反应

原因 :普通变量不具备响应式,Vue 无法追踪其变化。必须使用 refreactive 包裹。

javascript 复制代码
// ✅ 正确写法
const count = ref(0)
count.value++  // 页面自动更新

❓ 2. reactive 能不能用来包裹基础类型?

不能。 reactive 的参数必须是对象或数组。传入基础类型会失效或报错。如果你需要给一个数字做响应式,直接用 ref

javascript 复制代码
// ❌ 不可行
const num = reactive(100)  // 无效,num 不具备响应式

// ✅ 正确做法
const num = ref(100)

❓ 3. 忘记写 .value 怎么办?

javascript 复制代码
const msg = ref('hello')
msg = 'world'  // ❌ 这样相当于把 ref 对象整个替换掉了,响应式丢失!

// ✅ 正确:
msg.value = 'world'

记忆技巧 :把 ref 想象成一个盒子,数据装在盒子里。在 JS 中操作时,必须打开盒子(.value);在模板中,Vue 帮你自动打开。


❓ 4. 模板里 {``{ obj.name }} 为什么不写成 {``{ obj.value.name }}

Vue 的模板编译器会自动"解包"顶层的 ref 对象------这个特性叫做 ref 的自动解包(unwrap) 。所以模板中不需要 .value

html 复制代码
<!-- 模板中自动解包 -->
<p>{{ obj.name }}</p>  <!-- ✅ 正确 -->

<!-- 不需要这样写 -->
<p>{{ obj.value.name }}</p>  <!-- ❌ 错误 -->

❓ 5. reactive 对象解构后还保持响应式吗?

不会! 这是 reactive 的一个常见坑。

javascript 复制代码
const state = reactive({ count: 0, name: 'Vue' })

// ❌ 解构会丢失响应式!
const { count, name } = state
count++  // 页面不会更新

// ✅ 需要搭配 toRefs 保留响应式
const { count, name } = toRefs(state)
count.value++  // 页面正常更新

❓ 6. 如何决定用 CDN 引入还是工程化搭建?

场景 推荐方式
学习阶段、写 Demo、简单小工具 CDN 引入(本文所有示例均适用)
公司项目、中大型应用、多人协作 工程化搭建(Vite + Vue3 + Pinia)

📝 写在最后 :Vue3 的响应式系统是其灵魂所在。理解了 refreactive 的本质区别和适用场景,就掌握了 Vue3 组合式 API 最核心的一块拼图。建议读者将本文中的代码示例亲手敲一遍,并在浏览器控制台中修改数据,亲眼观察页面的变化------这是理解响应式最快的方式。

相关推荐
凉、介19 小时前
Virtio(三):Virtqueue 建立与 Buffer 提交
笔记·学习·嵌入式·arm·虚拟化·virtio
三水不滴19 小时前
RAG 评测数据集,到底该怎么准备?
经验分享·笔记
Lhappy嘻嘻19 小时前
网络(四)|全网最细网络层原理:IP 协议、IP 地址分类、子网划分、路由转发、NAT 穿透详解
java·笔记·网络协议·计算机网络
鱼子星_20 小时前
【C++】vector
开发语言·c++·笔记·stl
吃着火锅x唱着歌20 小时前
Effective C++ 学习笔记 条款38 通过复合塑模出has-a或“根据某物实现出”
c++·笔记·学习
syagain_zsx20 小时前
库制作与原理 · 链接知识笔记
c语言·c++·笔记·动态库·静态库
caimouse20 小时前
mm学习笔记_04:VAD树算法与地址空间分配
笔记·学习·算法·reactos
智者知已应修善业20 小时前
【使用D触发器74HC175实现0001 0011 0111 1111 1110 1100 1000的循环彩灯电路。】2025-4-28
驱动开发·经验分享·笔记·硬件架构·硬件工程
龙仔7251 天前
人大金仓KingbaseES V8 手动单库备份&恢复操作笔记
数据库·笔记·oracle·人大金仓