Vue3超详细教学(傻瓜版)百万字超详细-基础知识
一、核心指令:Vue 的 "万能工具箱"
Vue 的指令就像给 HTML 加了 "魔法 buff",让静态页面瞬间变动态 —— 不用写复杂 JS 操作 DOM,一个指令就能实现绑定、循环、显示隐藏等功能。下面逐个拆解,用 "梗 + 专业" 双模式讲透!
二、数据绑定三剑客:v-model + 插值显示
2.1 代码展示
▼javascript复制代码<script setup> import {ref} from "vue"; let name = ref('') // 定义一个字符串变量 </script> <template> <input v-model="name" type="text"> // 将输入框的输入内容绑定到变量 name <div>{{ name }}</div> // 使用插值方法,显示变量的值 </template>
2.2 梗版拆解
这俩组合就是 "输入框的回声机"—— 你在输入框里敲啥,下面的 div 就重复啥!
-
let name = ref(''):给 "回声机" 装了个空的 "存储盒",专门存输入的内容; -
v-model="name":给输入框绑了根 "数据线",输入的内容实时传到 "存储盒" 里; -
{{ name }}:给 div 装了个 "显示器",实时显示 "存储盒" 里的内容。比如你输入 "张三",输入框传数据到
name,div 马上显示 "张三",比回声还快!
2.3 专业版拆解
ref(''):Vue3 组合式 API 的响应式变量创建方法,ref包裹的变量会变成 "响应式对象"—— 值变化时,依赖它的 DOM 会自动更新(即 "响应式渲染");v-model:双向数据绑定指令,本质是value属性绑定 +input事件监听的语法糖,等价于:
▼html复制代码<input :value="name" @input="name = $event.target.value">
- 实现 "输入框值变→变量变→页面显示变" 的双向同步;
- 插值显示
{{ name }}:Mustache 语法,用于将响应式变量的值插入到 DOM 中,支持简单表达式(如{{ name + '你好' }}),但不支持复杂逻辑(如循环、条件判断)。
.4 实际用法扩展
- 适用场景:表单输入(输入框、单选框、复选框)、实时预览(如评论输入框实时显示字数);
- 注意:
v-model在不同表单元素上的绑定逻辑不同 —— 输入框绑定value,复选框绑定checked,下拉框绑定selected,但 Vue 会自动适配,不用手动处理。
三、显示隐藏开关:v-show
3.1 核心逻辑
梗版拆解
v-show就是页面元素的 "电灯开关"—— 接个布尔值(true/false),开(true)就亮(显示),关(false)就灭(隐藏)。
比如给 div 加v-show="isShow",isShow为 true 时 div 正常显示,为 false 时 div 会被加style="display: none"(相当于关灯,元素还在 DOM 里,只是看不见)。
专业版拆解
- 作用:根据布尔值控制元素的显示 / 隐藏,本质是通过修改元素的
displayCSS 属性实现(true→display: block/inline,false→display: none); - 特点:元素始终存在于 DOM 中,切换时仅修改样式,适合频繁切换显示状态的场景(如 tabs 切换),性能开销小;
- 对比后续
v-if:v-show是 "隐藏",v-if是 "销毁 / 创建",频繁切换用v-show,偶尔切换用v-if。
四、循环渲染神器:v-for
4.1 代码展示
▼javascript复制代码<script setup> import { ref } from 'vue' let list = ref(['苹果', '香蕉', '橙子']) </script> <template> <ul> <li v-for="(item, index) in list" :key="index"> <strong> {{ item }}</strong> <div> {{index}} </div> </li> </ul> </template>
4.2 梗版拆解
v-for就是 Vue 的 "自动生产线",把列表里的每个元素做成一个相同的 "零件"(li):
(item, index) in list:生产线的 "原料配方"——item是每个元素(比如 "苹果"),index是元素的 "编号"(0、1、2);:key="index":给每个零件贴个 "身份证号",Vue 靠这个识别元素,避免重复或错乱(比如删除一个元素时,Vue 知道该删哪个);- 最终生产线会造出 3 个 li,分别显示 "苹果(0)"、"香蕉(1)"、"橙子(2)"。
4.3 专业版拆解
- 语法格式:
v-for="(item, index) in 可迭代对象",可迭代对象包括数组、对象、字符串、数字; item与index:item是迭代的当前元素,index是可选参数(当前元素的索引,从 0 开始);:key的作用:Vue 的虚拟 DOM Diff 算法依赖key识别元素的唯一性,避免 "就地复用" 导致的渲染错误,推荐用唯一标识(如接口返回的id)作为key,而非index(index会随列表操作变化,可能引发问题);- 迭代对象扩展:
- 迭代对象:
v-for="(value, key) in user"(user是对象,key是属性名,value是属性值); - 迭代数字:
v-for="n in 5"(生成 5 个元素,n 从 1 到 5)。
- 迭代对象:
4.4 练习题
题目:用 v-for 循环渲染一个对象user = ref({name: '张三', age: 18, gender: '男'}),显示属性名和对应值。
答案:
▼javascript复制代码<script setup> import { ref } from 'vue' let user = ref({name: '张三', age: 18, gender: '男'}) </script> <template> <div v-for="(value, key) in user" :key="key"> {{ key }}: {{ value }} </div> </template>
显示效果:
name: 张三
age: 18
gender: 男
五、动态操作双雄:v-bind + v-on(@click)
5.1 代码展示
▼javascript复制代码import { ref } from 'vue' let imageUrl = ref('https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png') let count = ref(0) const handleClick = () => { count.value++ } </script> <template> <img :src="imageUrl" alt="p"> <button @click="handleClick">点击 {{ count }}</button> </template>
5.2 梗版拆解
这俩是 Vue 的 "动态操作组合拳"—— 一个管 "属性动态变",一个管 "事件动态触发":
:src="imageUrl"(v-bind 简写):给图片的 "地址属性" 绑了个 "遥控器",只要改imageUrl的值,图片就会自动换(比如把地址改成小猫图片,页面马上显示小猫);@click="handleClick"(v-on 简写):给按钮装了个 "触发开关",点击一次就执行handleClick函数 —— 这里的函数是 "计数器加 1",所以点一次,count就从 0 变成 1、2、3...,按钮上的数字也跟着更。
5.3 专业版拆解
5.3.1 v-bind(简写:)
- 作用:动态绑定 HTML 元素的属性或 Vue 组件的 props,让属性值随变量变化;
- 语法:
v-bind:属性名="变量"或:属性名="变量"; - 常见场景:绑定图片
src、链接href、样式class/style、组件 props 等,例如:
▼html复制代码<a :href="link">跳转</a> <div :class="{ active: isActive }"></div> <!-- 动态绑定类名 -->
5.3.2 v-on(简写@)
- 作用:绑定 DOM 事件或自定义事件,触发指定函数;
- 语法:
v-on:事件名="函数"或@事件名="函数"; - 事件对象:函数可接收
$event参数获取事件对象,例如:
▼html复制代码<button @click="handleClick($event)">点击</button>
▼javascript复制代码const handleClick = (e) => { console.log(e.target) // 打印点击的按钮元素 }
- 常见事件:
click(点击)、input(输入)、change(变化)、mouseenter(鼠标移入)等。
讲解一下handleClick函数
const handleClick:声明一个常量handleClick,存储箭头函数。(e):函数的参数e是事件对象(Event Object),当事件触发时(比如点击),浏览器会自动传递这个对象,包含了事件相关的信息(如触发事件的元素、事件类型等)。- 箭头函数
=>:ES6 语法,等价于传统的function定义(这里功能上等同于function handleClick(e) { ... })。
箭头函数
| 场景 | 传统 function 函数 | 箭头函数 | 说明 |
|---|---|---|---|
| 无参数 | function() { ... } | () => { ... } | 箭头前用 () 表示无参数 |
| 单个参数 | function(a) { ... } | a => { ... } | 单个参数可以省略 () |
| 多个参数 | function(a, b) { ... } | (a, b) => { ... } | 多个参数必须用 () 包裹 |
| 函数体只有一行代码 | function(a) { return a + 1; } | a => a + 1 | 可省略 {} 和 return(自动返回结果) |
| 函数体多行代码 | function(a) { let b = 2; return a + b; } | a => { let b = 2; return a + b; } | 必须用 {} 包裹,且显式写 return |
5.4 练习题
题目:用 v-bind 绑定一个按钮的 disabled 属性(当 count>=3 时禁用按钮),点击按钮 count 减 1。
▼javascript复制代码<script setup> import { ref } from 'vue' let count = ref(3) const handleMinus = () => { count.value-- } </script> <template> <button @click="handleMinus" :disabled="count >= 3">count: {{ count }}</button> </template>
六、条件渲染王者:v-if /v-else
6.1 代码展示
▼javascript复制代码<script setup> import { ref } from 'vue' let isVisible = ref(true) </script> <template> <button @click="isVisible = !isVisible">切换显示</button> <div v-if="isVisible">显示内容 AA</div> <h1 v-else>显示内容 BB</h1> </template>
6.2 梗版拆解
v-if和v-else是页面的 "二选一开关"—— 根据条件决定显示哪部分内容:
- 初始
isVisible是 true,显示 "AA",隐藏 "BB"; - 点击按钮,
isVisible变成 false,就隐藏 "AA",显示 "BB"; - 注意:这俩必须是 "邻居",中间不能夹其他不带 v-if 的元素(比如把按钮放中间,Vue 就分不清谁和谁是一组,会报错)。
6.3 专业版拆解
-
作用:根据布尔值条件渲染元素,条件为 true 时渲染
v-if对应的元素,否则渲染v-else对应的元素; -
特点:元素不存在于 DOM 中(条件不满足时会被销毁),适合不频繁切换的场景(如登录 / 未登录状态显示不同内容);
-
嵌套用法:支持
v-if→v-else-if→v-else多条件判断,例如:html
预览
▼html复制代码<div v-if="score >= 90">优秀</div> <div v-else-if="score >= 60">及格</div> <div v-else>不及格</div> -
语法限制:
v-if、v-else-if、v-else必须连续相邻,中间不能插入其他 DOM 元素,否则 Vue 无法识别条件分组,导致渲染错误。
6.4 v-if 与 v-show 的核心区别
| 特性 | v-if | v-show |
|---|---|---|
| 渲染方式 | 条件满足则创建,否则销毁 | 始终创建,通过 display 控制显示 / 隐藏 |
| 性能开销 | 切换时开销大(DOM 操作) | 切换时开销小(样式操作) |
| 适用场景 | 不频繁切换(如登录状态) | 频繁切换(如 tabs 切换) |
| 初始渲染开销 | 条件不满足时开销小 | 无论条件如何都有初始开销 |
七、HTML 渲染神器:v-html
7.1 代码展示
▼javascript复制代码<script setup> import { ref } from 'vue' let htmlContent = ref('<h1>这是一个HTML内容</h1>') </script> <template> <div v-html="htmlContent"></div> </template>
7.2 梗版拆解
v-html是 Vue 的 "HTML 翻译官"—— 把字符串里的 HTML 标签翻译成真实的页面元素:
-
如果你直接用
{{ htmlContent }},页面会显示<h1>这是一个HTML内容</h1>(把标签当普通文字); -
用了
v-html,翻译官会识别<h1>标签,渲染成一个真正的大标题,显示效果就是 "这是一个 HTML 内容"(加粗放大)。就像你给机器输入 ",标题。你好",机器直接显示成标题样式,而不是原始文本。
7.3 专业版拆解
- 作用:将字符串形式的 HTML 内容渲染为真实的 DOM 元素,替代插值语法(插值语法会转义 HTML 标签);
- 适用场景:渲染富文本内容(如博客、评论、编辑器输出的 HTML 代码);
- 安全风险:严禁用
v-html渲染用户输入的内容(如用户评论),可能导致 XSS 攻击(恶意用户注入恶意 HTML/JS 代码,窃取信息或攻击网站); - 对比插值语法:
- 插值语法:
{{ '<h1>你好</h1>' }}→ 显示文本<h1>你好</h1>; - v-html:
<div v-html="'<h1>你好</h1>'"></div>→ 显示 h1 标签的 "你好"。
- 插值语法:
八、组件通信利器:v-slot(插槽)
8.1 核心逻辑(简化版)
梗版拆解
v-slot是父子组件的 "快递代收点"—— 子组件留个 "收件箱"(<slot>标签),父组件把内容通过 "指定收件箱"(v-slot:name)寄过去,子组件就能显示父组件的内容:
- 子组件(Child.vue):留个叫 "header" 的插槽(收件箱):
▼html复制代码<template> <div> <slot name="header"></slot> <!-- 收件箱:header --> <div>子组件默认内容</div> </div> </template>
父组件:给子组件的 "header" 插槽寄内容(放个标题)
▼html复制代码<template> <Child> <template v-slot:header> <h1>这是父组件的标题</h1> <!-- 要寄的内容 --> </template> </Child> </template>
- 最终子组件会显示 "父组件的标题" + "子组件默认内容",实现父子组件内容灵活传递。
专业版拆解
- 作用:实现父子组件间的内容分发,让父组件可以向子组件指定位置插入自定义内容;
- 核心概念:
- 插槽(slot):子组件中用
<slot>标签定义的 "占位符",父组件可在这些位置插入内容; - 具名插槽:带
name属性的插槽(如slot name="header"),父组件用v-slot:name(简写#name)指定插入的插槽; - 默认插槽:无
name属性的插槽,父组件未指定插槽的内容会插入默认插槽;
- 插槽(slot):子组件中用
- 简写语法:
v-slot:header可简写为#header,更简洁
▼html复制代码<template #header> <h1>父组件标题</h1> </template>
8.2 适用场景
- 通用组件封装(如弹窗组件,父组件可自定义弹窗标题、内容、按钮);
- 内容灵活替换(如卡片组件,不同页面使用时可插入不同的头部 / 底部内容)。
九、Vue 组件命名规范:避免踩坑的 "起名指南"
9.1 核心规范(梗版 + 专业版)
梗版
给组件起名就像给孩子起名 —— 要规范、好认、不撞名:
- 不能叫 "div"、"button"(和 HTML 标签重名,Vue 会 confused);
- 多单词要大写开头(比如
UserLogin)或短横线连接(user-login),别瞎写userlogin(分不清是 "user login" 还是 "userlog in"); - 文件名和组件名要一样(比如组件叫
UserLogin,文件就叫UserLogin.vue),不然找组件时像找 "张小三" 却搜 "张三",找不到!
专业版
- 命名格式:
- 推荐使用
PascalCase(大驼峰,如UserLogin):适用于单文件组件(.vue)、字符串模板、JSX; - 必须使用
kebab-case(短横线,如user-login):适用于 DOM 模板(HTML 文件中的模板),因为 HTML 不区分大小写,UserLogin会被解析为userlogin,导致组件识别失败;
- 推荐使用
- 命名规则:
- 多单词命名:避免与 HTML 原生标签(如
div、span、button)冲突; - 语义化命名:根据组件功能命名(如
UserLogin表示用户登录组件,GoodsCard表示商品卡片组件);
- 多单词命名:避免与 HTML 原生标签(如
- 文件命名:组件文件名与组件名保持一致(如
UserLogin.vue对应UserLogin组件),便于项目结构维护和查找。
9.2 错误示例 vs 正确示例
| 场景 | 错误命名 | 正确命名 | |
|---|---|---|---|
| 单文件组件 | userlogin.vue | UserLogin.vue | |
| DOM 模板使用 | <UserLogin> | <user-login> | |
| 组件名 | Button | MyButton | (避免与原生<button>冲突) |
十、关键避坑:为什么不建议 v-if 和 v-for 一起用?
10.1 梗版拆解
这俩一起用就像 "边炒菜边洗菜"—— 要么效率低,要么炒糊:
- Vue2 里:
v-for优先级高,先循环再判断,比如循环 100 个元素,每个都要判断一次 "显不显示",累死 Vue; - Vue3 里:
v-if优先级高,先判断再循环,结果v-if里拿不到循环的变量(比如v-if="item.isShow",Vue3 会说 "item 是谁?我不认识"),直接报错; - 更坑的是:Vue2 和 Vue3 的优先级不一样,你在 Vue2 写的代码移到 Vue3,原本能跑,现在直接崩,找 bug 找半天!
10.2 专业版拆解
- Vue2 与 Vue3 的优先级差异:
- Vue2:
v-for优先级 >v-if优先级,v-if会在每个循环迭代中执行,导致不必要的性能开销(如循环 100 个元素,每个都要执行一次v-if判断); - Vue3:
v-if优先级 >v-for优先级,v-if无法访问v-for作用域内的变量(如item、index),会抛出 "变量未定义" 的错误;
- Vue2:
- 性能与兼容性问题:
- 性能:Vue2 中频繁循环 + 判断会消耗 DOM 渲染性能;
- 兼容性:优先级差异导致代码在不同 Vue 版本中行为不一致,维护成本高;
- 解决方案:
- 用
<template>包裹:将v-for放在<template>上,v-if放在子元素上(<template>不会渲染为真实 DOM);
- 用
▼html复制代码<template v-for="item in list" :key="item.id"> <div v-if="item.isVisible">{{ item.name }}</div> </template>
先过滤列表:在 JS 中用computed过滤出需要渲染的元素,再用v-for循环(推荐,性能最优)
▼javascript复制代码const filteredList = computed(() => list.value.filter(item => item.isVisible))
filteredList讲解
-
computed是什么?computed是 Vue 3 提供的计算属性 API,用于定义一个依赖响应式数据的计算值。它的特点是:- 当依赖的数据(这里是
list.value)发生变化时,会自动重新计算结果。 - 结果会被缓存,只有依赖变化时才会重新计算,提升性能。
- 当依赖的数据(这里是
-
箭头函数的作用:
computed(() => { ... })中的箭头函数是计算属性的「 getter 」,定义了计算逻辑。list.value.filter(item => item.isVisible)是核心过滤逻辑:list是一个 Vue 响应式数据(通常由ref或reactive定义),list.value是获取其原始值(数组)。filter是数组方法,用于过滤出符合条件的元素。这里的条件是item.isVisible(即只保留isVisible为true的元素)。- 箭头函数
item => item.isVisible等价于function(item) { return item.isVisible; },简化了写法。
-
最终效果:
filteredList会实时返回list中所有isVisible为true的元素组成的新数组,且随list变化自动更新。
▼html复制代码<div v-for="item in filteredList" :key="item.id">{{ item.name }}</div>
十一、小结:Vue 指令 & 规范核心要点
- 核心指令:
- 数据绑定:
v-model(双向)、{{ }}(插值); - 条件渲染:
v-if(销毁 / 创建)、v-show(显示 / 隐藏); - 循环渲染:
v-for(加:key); - 动态操作:
v-bind(属性)、v-on(事件); - 特殊渲染:
v-html(HTML 内容)、v-slot(插槽);
- 数据绑定:
- 组件规范:多单词命名,大驼峰 / 短横线区分场景,文件名与组件名一致;
- 避坑重点:不混用
v-if和v-for,优先用<template>或computed替代。
掌握这些,你就能用 Vue 写出灵活、规范、高性能的动态页面啦!

