VUE 复习笔记
Vue.js 四大文件关系
| 前端文件 / 角色 | 生活类比 | 核心定位 |
|---|---|---|
index.html |
毛坯房(空房子) | 最外层载体,只有框架,无实际装修 |
main.js |
搬家工人 + 总负责人 | 执行搬运、组装、挂载,统筹整体 |
App.vue |
硬装(墙体 / 吊顶 / 水电 / 全屋骨架) | 项目根骨架,固定整体布局 |
自定义组件(xxx\.vue) |
软装(家具 / 灯具 / 挂画 / 摆件) | 可复用、可自由搭配的功能模块 |
一、逐个拆解讲解
1. index.html = 毛坯房
特点
房子本身存在,有墙体、门洞、空间框架,但空空如也,没有任何家具和装修 。
只预留了一个专属摆放区域 (对应 <div id="app">)。
对应代码逻辑:
index.html 是浏览器最先加载的静态页面,整个 Vue 项目最终都要放进它里面,它只提供容器,不写业务代码、不做页面渲染。
类比:毛坯房只是一个 "场地",所有装修、家具都要放在这个场地里。
2. main.js = 搬家工人(总调度)
特点
搬家工人负责:
-
把硬装主体(App.vue) 搬进毛坯房;
-
把所有软装(自定义组件) 配套就位;
-
固定位置、完成整体 "安装";
-
额外统筹:全屋通用物件(全局组件、路由、工具)统一摆放。
对应代码逻辑:
-
main.js是项目启动入口; -
导入根组件
App.vue,调用createApp()创建 Vue 应用; -
通过
.mount('#app'),把整套 Vue 项目 "搬进" index.html 的容器中; -
全局组件、路由、第三方库也在这里统一配置(相当于全屋共用物品统一安置)。
类比:没有搬家工人,硬装、软装都进不了毛坯房,房子永远是空的。
3. App.vue = 硬装(全屋基础骨架)
特点
硬装是房子的根基:墙面、地面、吊顶、门窗、水电、全屋分区布局。
-
一旦完工,整体结构固定;
-
所有家具、摆件(软装)都必须摆放在硬装划定的区域里;
-
整间屋子只有一套主硬装 (对应项目只有一个根组件
App.vue)。
对应代码逻辑:
-
App.vue是 Vue 项目唯一根组件,搭建页面整体布局(导航、侧边栏、底部、路由出口等); -
它是所有子组件的 "父容器",所有自定义组件都要嵌套在它内部使用;
-
结构稳定,是整个项目的核心骨架。
类比:硬装决定了房子长什么样、区域怎么划分,软装只能在硬装基础上搭配。
4. 自定义组件 = 软装(家具 / 装饰)
特点
软装:沙发、桌椅、灯具、挂画、窗帘、摆件......
-
可复用:同款椅子可以放客厅、也可以放书房;
-
可自由搭配:想换、想增删都很灵活,不改动房屋硬装;
-
必须摆放在硬装划定的区域内,不能脱离房子单独存在。
对应代码逻辑:
-
按钮、卡片、列表、页面模块等自定义组件,都是可复用单元;
-
必须被
App.vue或其他父组件引入使用,无法直接挂载到index.html; -
增删、修改单个组件,不会影响项目整体骨架。
类比:换沙发、加挂画,不用砸墙改硬装;对应:修改子组件,不影响根组件整体结构。
二、完整流程串讲(从空房到入住)
结合加载顺序,走一遍完整场景:
-
拿到毛坯房(index.html)
浏览器打开网址,加载空白
index.html,就像拿到一间空荡荡的房子,只留好了摆放位置。 -
搬家工人进场(执行 main.js)
工具自动运行
main.js,工人开始干活:-
先把全屋硬装(App.vue) 搬进房子、固定到位;
-
顺便把全屋通用物品(全局组件)提前布置好。
-
-
硬装成型(渲染 App.vue)
硬装搭建完成,房子有了墙体、分区、基础布局(页面全局结构)。
-
摆放软装(渲染自定义组件)
在硬装的各个区域里,依次摆放沙发、灯具、家具(渲染各类子组件)。
-
最终效果
毛坯房 + 硬装 + 软装 组合成完整可入住的房子
↔
index.html + App.vue + 自定义组件 组合成完整可浏览的网页。
三、补充关键规则(结合生活场景理解)
-
硬装不能脱离毛坯房
App.vue必须通过main.js挂载到index.html,不能单独运行。 -
软装不能脱离硬装
自定义组件必须被父组件(优先 App.vue)引用,不能直接放到 index.html。
-
搬家工人只负责搬运安装,不改变房屋结构
main.js只做导入、创建、挂载、全局配置,不编写页面具体结构。 -
硬装改起来麻烦,软装灵活多变
修改
App.vue会影响全站布局;增删改自定义组件,影响范围小、维护简单。
Vue.js 基础入门
一、Vue.js 概述
1. 什么是 Vue.js
Vue是开源渐进式JavaScript框架 ,专注于视图层,用于开发交互式网页界面、单页应用。
-
渐进式:可按需使用,从简单页面嵌入逐步扩展为大型项目,不用一次性接受全部功能。
-
易上手:基于HTML、CSS、JavaScript,前端开发者可快速入门。
-
轻量高效:压缩后仅20KB左右,加载速度快。
-
灵活性:可嵌入现有项目,也可独立开发完整SPA。
2. Vue 核心特性
-
虚拟DOM:内存中虚拟节点树,减少真实DOM操作,提升性能。
-
数据绑定:通过指令绑定数据与DOM,数据变化自动更新页面。
-
组件化:封装可复用UI模块,解耦代码。
-
指令系统 :内置
v-if/v-for/v-model等指令,简化DOM操作。 -
事件处理:简洁语法监听鼠标、键盘等DOM事件。
-
过渡&动画:内置过渡组件,轻松实现入场/出场动画。
-
计算属性:基于现有数据动态计算新值,缓存结果提升效率。
3. DOM 与 虚拟DOM(Virtual DOM)
(1)原生DOM 缺点
真实DOM是浏览器渲染页面的节点树,频繁修改DOM会触发页面重排/重绘,页面元素越多,性能损耗越大。
(2)Vue 虚拟DOM 工作原理(6步流程)
虚拟DOM是真实DOM的轻量级副本 ,存于内存中,Vue通过对比算法(Diff) 最小化DOM修改:
-
初始渲染:根据模板生成虚拟DOM,渲染为真实DOM展示页面。
-
数据变更 :页面数据发生修改,Vue生成全新虚拟DOM。
-
Diff对比 :对比新旧虚拟DOM,找出发生变化的节点。
-
生成补丁:仅针对变化节点生成修改指令(Patch)。
-
应用补丁:只更新真实DOM中变化的部分,而非全量刷新。
-
同步完成:真实DOM与最新数据保持一致。
核心优势:只操作局部DOM,大幅提升页面渲染性能。
4. Vue 环境搭建(Vue 3 + Vue CLI)
前置条件
安装 Node.js(自带npm包管理工具),用于安装Vue CLI、管理项目依赖。
完整安装步骤
- 校验Node和npm是否安装成功(终端执行)
Bash
node -v # 查看Node版本
npm -v # 查看npm版本
- 全局安装 Vue CLI(Vue官方脚手架)
Bash
npm install -g @vue/cli
- 校验Vue CLI
Bash
vue --version
- 创建Vue 3项目
Bash
vue create my-vue-project # my-vue-project 为项目名
-
选择
Manually select features(手动选择功能) -
勾选:Babel、Router、Vuex、Linter
-
选择
Vue 3.x版本
- 运行开发服务器
Bash
cd my-vue-project # 进入项目文件夹
npm run serve # 启动本地开发服务,浏览器访问默认地址即可预览
补充:Vite(更快的构建工具)
Vite启动速度远快于Vue CLI,创建Vue项目命令:
Bash
npm create vue@latest my-project
cd my-project
npm install
npm run dev
5. Vue CLI 项目目录结构
Plaintext
my-vue-project/
├── node_modules/ # 项目所有依赖包(第三方库)
├── public/ # 静态资源(图片、静态html,不会被打包编译)
│ └── index.html # 项目入口HTML文件
├── src/ # 源代码目录(核心开发文件夹)
│ ├── assets/ # 项目资源(图片、全局CSS,会被打包)
│ ├── components/ # 可复用小组件
│ ├── router/ # 路由配置(页面跳转)
│ ├── store/ # Vuex状态管理(全局数据)
│ ├── views/ # 页面级大组件
│ ├── App.vue # 根组件(整个项目的根容器)
│ └── main.js # 项目入口JS文件(创建Vue实例、挂载应用)
├── package.json # 项目配置、脚本命令、依赖清单
└── README.md # 项目说明文档
6. Vue 单文件组件(.vue 文件)结构
.vue是Vue专属单文件组件 ,一个文件封装模板、脚本、样式三部分,结构固定:
Plaintext
<!-- 1. template:HTML模板区域,编写页面结构(必写) -->
<template>
<div>页面HTML内容</div>
</template>
<!-- 2. script:JS逻辑区域,编写数据、方法、组件注册等 -->
<script>
export default {
name: "组件名", // 组件名称
data() { // 组件数据
return {}
},
methods: {} // 组件方法
}
</script>
<!-- 3. style:样式区域,scoped表示样式仅作用于当前组件 -->
<style scoped>
/* CSS样式 */
</style>
scoped关键字:样式私有化,不会污染其他组件样式。
7. 常用Vue CLI 命令
Bash
vue create 项目名 # 创建新项目
npm run serve # 启动开发环境(热更新,开发使用)
npm run build # 打包项目(生成dist文件夹,用于线上部署)
Vue 3 组件(核心:复用、通信、注册)
组件是Vue的核心单元,将页面拆分为独立、可复用的UI模块,每个组件拥有独立结构、数据、样式。
一、基础简单组件(可复用UI)
1. 代码示例
1)子组件:components/BasicComponent.vue(可复用组件)
Plaintext
<template>
<div class="my-component">
<h1>来自可复用组件</h1>
<p>我是独立可复用的Vue组件</p>
</div>
</template>
<script>
export default {
name: "BasicComponent" // 定义组件名称,一般和文件名一致
};
</script>
<!-- scoped:样式仅当前组件生效 -->
<style scoped>
.my-component {
border: 2px solid green;
padding: 20px;
margin: 10px;
background-color: #e8f5e9;
border-radius: 10px;
}
</style>
2)根组件:App.vue(引入并使用子组件)
Plaintext
<template>
<div id="app">
<h1>Vue 组件演示</h1>
<!-- 多次使用组件:体现复用性 -->
<BasicComponent />
<BasicComponent />
<BasicComponent />
</div>
</template>
<script>
// 1. 导入子组件
import BasicComponent from "./components/BasicComponent.vue";
export default {
name: "App",
// 2. 局部注册组件
components: { BasicComponent }
};
</script>
2. 代码详解
-
组件可以重复调用,实现UI复用;
-
style scoped保证组件样式隔离,多个组件不会样式冲突; -
组件拆分:复杂页面拆分为多个小组件,代码更易维护。
二、组件 data 必须是函数(数据隔离核心)
1. 核心规则(Vue 3 强制要求)
-
✅ 正确写法 :
data() { return {} }(函数形式) -
❌ 错误写法 :
data: {}(对象形式,Vue会报错)
原因 :组件会被多次复用,若data是普通对象,所有组件实例共享同一份数据 ,修改一个会影响全部;
data写成函数,每次创建组件都会返回全新对象 ,每个实例拥有独立数据,实现数据隔离。
2. 计数器案例(数据隔离演示)
子组件:ClickCounter.vue
Plaintext
<template>
<div class="counter-box">
<h3>点击计数器</h3>
<p>点击次数:<strong>{{ count }}</strong></p>
<button @click="count++">点击我</button>
<p>组件唯一ID:{{ componentId }}</p>
</div>
</template>
<script>
export default {
name: "ClickCounter",
// data 必须是函数,返回新对象
data() {
return {
count: 0, // 点击次数
// 随机生成唯一ID,证明每个组件是独立实例
componentId: Math.random().toString(36).substr(2, 4)
};
}
};
</script>
<style scoped>
.counter-box {
border: 2px solid orange;
padding: 15px;
margin: 10px;
display: inline-block;
width: 200px;
text-align: center;
}
</style>
App.vue 使用组件
Plaintext
<template>
<div>
<h1>组件数据隔离演示</h1>
<!-- 三个独立计数器,互不干扰 -->
<ClickCounter />
<ClickCounter />
<ClickCounter />
</div>
</template>
<script>
import ClickCounter from "./components/ClickCounter.vue";
export default {
components: { ClickCounter }
};
</script>
3. 效果说明
点击任意一个计数器按钮,仅当前组件数字变化,其他组件不受影响,证明数据完全隔离。
三、组件注册方式(局部注册 + 全局注册)
1. 局部注册(推荐,主流用法)
特点
-
组件仅在当前父组件内可用,外部无法使用;
-
避免全局命名冲突,减少项目体积,大型项目首选。
代码示例
1)子组件:SpecialButton.vue
Plaintext
<template>
<button class="special-btn">局部组件按钮</button>
</template>
<script>
export default { name: "SpecialButton" };
</script>
<style scoped>
.special-btn { background: purple; color: white; padding: 10px; }
</style>
2)父组件:ParentBox.vue(局部注册)
Plaintext
<template>
<div class="parent-box">
<h3>父组件</h3>
<!-- 仅当前组件可使用 SpecialButton -->
<SpecialButton />
</div>
</template>
<script>
// 导入子组件
import SpecialButton from "./SpecialButton.vue";
export default {
name: "ParentBox",
// 局部注册:仅本组件生效
components: { SpecialButton }
};
</script>
<style scoped>
.parent-box { border: 3px solid blue; padding: 20px; }
</style>
3)App.vue
Plaintext
<template>
<div>
<ParentBox />
<!-- 直接使用 SpecialButton 会报错:组件未注册 -->
<!-- <SpecialButton /> -->
</div>
</template>
<script>
import ParentBox from "./components/ParentBox.vue";
export default { components: { ParentBox } };
</script>
2. 全局注册(全局可用)
特点
-
在
main.js中一次性注册,整个项目所有组件都能直接使用,无需重复导入; -
适合高频通用组件(弹窗、全局按钮、通知提示)。
代码示例
1)全局组件:GlobalAlert.vue
Plaintext
<template>
<!-- v-if 控制组件显示/隐藏 -->
<div class="alert-box" v-if="isVisible">
<h3>{{ title }}</h3>
<p>{{ message }}</p>
<button @click="closeAlert">关闭</button>
</div>
</template>
<script>
export default {
name: "GlobalAlert",
// 接收外部传入的参数
props: {
title: { type: String, default: "通知" },
message: { type: String, default: "全局提示消息" }
},
data() {
return { isVisible: true };
},
methods: {
closeAlert() {
this.isVisible = false; // 关闭提示
}
}
};
</script>
2)main.js(全局注册入口)
JavaScript
import { createApp } from "vue";
import App from "./App.vue";
// 导入全局组件
import GlobalAlert from "./components/GlobalAlert.vue";
const app = createApp(App);
// 全局注册:所有组件均可使用 GlobalAlert
app.component("GlobalAlert", GlobalAlert);
app.mount("#app"); // 挂载Vue实例
3)App.vue(直接使用,无需导入)
Plaintext
<template>
<div>
<!-- 全局组件,直接使用 -->
<GlobalAlert title="欢迎" message="全局组件演示" />
<GlobalAlert title="优惠活动" message="全场5折" />
</div>
</template>
四、动态组件 <component :is>
1. 作用
运行时动态切换不同组件,常用于标签页、步骤向导、选项卡场景,无需路由即可切换UI。
2. 核心语法
Plaintext
<!-- is 绑定组件名称/组件对象,动态渲染对应组件 -->
<component :is="当前组件变量"></component>
3. 完整代码示例
1)三个页面组件(HomePage、AboutPage、ContactPage)
Plaintext
<!-- HomePage.vue -->
<template><div class="page">首页</div></template>
<style scoped>.page{background:#e3f2fd;padding:20px;}</style>
<!-- AboutPage.vue -->
<template><div class="page">关于我们</div></template>
<style scoped>.page{background:#f3e5f5;padding:20px;}</style>
<!-- ContactPage.vue -->
<template><div class="page">联系我们</div></template>
<style scoped>.page{background:#e8f5e9;padding:20px;}</style>
2)动态标签页组件 DynamicTabs.vue
Plaintext
<template>
<div>
<!-- 标签按钮:点击切换组件 -->
<div class="tabs">
<button
v-for="tab in tabs"
:key="tab.name"
@click="currentTab = tab.component"
:class="{ active: currentTab === tab.component }"
>
{{ tab.name }}
</button>
</div>
<!-- 动态组件:根据 currentTab 渲染对应组件 -->
<component :is="currentTab" />
</div>
</template>
<script>
// 导入三个子组件
import HomePage from "./HomePage.vue";
import AboutPage from "./AboutPage.vue";
import ContactPage from "./ContactPage.vue";
export default {
name: "DynamicTabs",
data() {
return {
currentTab: HomePage, // 默认显示首页组件
// 标签列表:名称 + 对应组件
tabs: [
{ name: "首页", component: HomePage },
{ name: "关于", component: AboutPage },
{ name: "联系", component: ContactPage }
]
};
}
};
</script>
<style scoped>
.tabs button { padding: 10px 20px; margin-right: 10px; cursor: pointer; }
.tabs .active { background: #42b983; color: white; border: none; }
</style>
3)App.vue 使用
Plaintext
<template>
<div>
<h1>动态组件-标签页</h1>
<DynamicTabs />
</div>
</template>
<script>
import DynamicTabs from "./components/DynamicTabs.vue";
export default { components: { DynamicTabs } };
</script>
4. 代码解析
-
currentTab存储当前激活的组件对象; -
点击标签按钮,修改
currentTab,<component :is>自动切换渲染组件; -
纯前端组件切换,不刷新页面,体验接近SPA。
五、组件鼠标事件(@mouseover / @mouseout)
实现鼠标悬浮、离开触发逻辑,结合组件数据隔离,每个组件独立响应。
完整代码(InteractiveCard.vue)
Plaintext
<template>
<!-- 绑定鼠标悬浮、离开事件 -->
<div
class="interactive-card"
@mouseover="handleMouseOver"
@mouseout="handleMouseOut"
>
<h2>
城市:
<span :style="{ color: textColor }">{{ cityName }}</span>
</h2>
<!-- v-if 条件渲染提示文本 -->
<p v-if="isHovered" class="message">鼠标已悬浮</p>
</div>
</template>
<script>
export default {
name: "InteractiveCard",
// 每个组件独立数据
data() {
return {
cityName: "上海",
isHovered: false,
textColor: "blue"
};
},
methods: {
// 鼠标悬浮事件
handleMouseOver() {
this.cityName = "贵州";
this.isHovered = true;
this.textColor = "red";
},
// 鼠标离开事件
handleMouseOut() {
this.cityName = "上海";
this.isHovered = false;
this.textColor = "blue";
}
}
};
</script>
<style scoped>
.interactive-card {
border: 2px solid #42b983;
padding: 20px;
margin: 15px;
display: inline-block;
width: 280px;
cursor: pointer;
transition: all 0.3s;
}
.interactive-card:hover {
transform: scale(1.02); /* 悬浮放大 */
box-shadow: 0 5px 15px #ccc;
}
.message {
background: #fff3cd;
padding: 10px;
border-radius: 5px;
}
</style>
使用与效果
在App.vue中多次引用组件,悬浮其中一个卡片,仅当前卡片变化,其他不受影响,验证组件数据隔离。
Vue 3 事件处理
Vue 使用 v-on 指令(简写 @)监听DOM事件,支持原生事件、事件修饰符、按键修饰符、自定义事件。
一、基础点击事件 @click
1. 语法
-
完整写法:
v-on:click="方法名" -
简写(推荐):
@click="方法名"
2. 代码示例(点击计算)
Plaintext
<template>
<div class="demo">
<button @click="displayNumbers">点击计算 50 + 100</button>
<h2>计算结果:{{ total }}</h2>
</div>
</template>
<script>
export default {
data() {
return {
num1: 50,
num2: 100,
total: ""
};
},
methods: {
// 点击触发的方法,可接收原生event对象
displayNumbers(event) {
console.log(event); // 打印原生点击事件对象
this.total = this.num1 + this.num2;
}
}
};
</script>
解析
-
按钮被点击时,执行
displayNumbers方法; -
方法可接收
event参数,获取原生DOM事件信息; -
修改data中的
total,页面自动更新(数据驱动视图)。
二、事件修饰符(.once / .prevent)
事件修饰符以.开头,用于简化原生JS的事件处理逻辑,Vue内置常用修饰符。
1. .once 只触发一次
作用
事件仅执行第一次,后续点击/触发无效。
代码示例
Plaintext
<template>
<div>
<!-- 点击仅生效一次 -->
<button @click.once="addOnce">只可点击一次</button>
<p>计数:{{ num1 }}</p>
<!-- 普通点击,无限触发 -->
<button @click="addNormal">可重复点击</button>
<p>计数:{{ num2 }}</p>
</div>
</template>
<script>
export default {
data() {
return { num1: 0, num2: 0 };
},
methods: {
addOnce() { this.num1++; },
addNormal() { this.num2++; }
}
};
</script>
2. .prevent 阻止默认行为
作用
等价于原生 event.preventDefault(),阻止标签默认动作(如a标签跳转、表单提交)。
代码示例
Plaintext
<template>
<div>
<!-- 加 .prevent:阻止a标签默认跳转 -->
<a href="https://www.baidu.com" @click.prevent="clickA">阻止跳转</a>
<!-- 无修饰符:点击后先弹窗,再跳转页面 -->
<a href="https://www.baidu.com" @click="clickANormal">正常跳转</a>
</div>
</template>
<script>
export default {
methods: {
clickA() { alert("已阻止跳转"); },
clickANormal() { alert("即将跳转"); }
}
};
</script>
三、按键修饰符(键盘事件)
监听键盘按键,基于@keyup/@keydown,Vue内置常用按键别名:
enter、tab、delete、esc、space、up/down/left/right,支持组合键(ctrl/alt/shift)。
代码示例
Plaintext
<template>
<div>
<p>输入内容后按 回车 提交</p>
<input
type="text"
v-model="name"
@keyup.enter="showName"
placeholder="按Enter提交"
>
<p>结果:{{ resultName }}</p>
<p>输入内容后按 Ctrl + 回车 提交</p>
<input
type="text"
v-model="msg"
@keyup.ctrl.enter="showMsg"
placeholder="按Ctrl+Enter提交"
>
<p>结果:{{ resultMsg }}</p>
</div>
</template>
<script>
export default {
data() {
return {
name: "",
resultName: "",
msg: "",
resultMsg: ""
};
},
methods: {
showName() {
this.resultName = this.name;
},
showMsg() {
this.resultMsg = this.msg;
}
}
};
</script>
解析
-
@keyup.enter:按下回车键触发方法; -
@keyup.ctrl.enter:组合键,必须同时按下Ctrl+回车才触发; -
v-model双向绑定输入框内容。
四、自定义事件(子组件 → 父组件通信)
组件通信核心方案:子组件通过 $emit 触发自定义事件并传值,父组件通过 @自定义事件名 监听。
完整案例
1)子组件 LanguageButton.vue(发送事件)
Plaintext
<template>
<!-- 点击按钮,触发自定义事件 -->
<button @click="sendData">{{ item }}</button>
</template>
<script>
export default {
// 接收父组件传递的数据
props: ["item"],
methods: {
sendData() {
// $emit("自定义事件名", 传递的数据)
this.$emit("showLanguage", this.item);
}
}
};
</script>
2)父组件(监听自定义事件)
Plaintext
<template>
<div>
<p>选中的语言:<b>{{ selectLang }}</b></p>
<!--
1. 循环渲染子组件,传递item数据
2. @showLanguage 监听子组件触发的自定义事件
-->
<LanguageButton
v-for="lang in langList"
:key="lang"
:item="lang"
@showLanguage="getLang"
/>
</div>
</template>
<script>
import LanguageButton from "./LanguageButton.vue";
export default {
components: { LanguageButton },
data() {
return {
selectLang: "",
langList: ["Java", "Python", "JavaScript", "C++"]
};
},
methods: {
// 接收子组件传递的值
getLang(val) {
this.selectLang = val;
}
}
};
</script>
流程总结
-
父组件循环创建子组件,通过
props给子组件传值; -
子组件点击按钮,调用
$emit("事件名", 数据)向外派发自定义事件; -
父组件用
@事件名监听,接收子组件传来的数据,更新页面。
条件渲染、列表渲染、过渡与动画
一、条件渲染指令:v-if / v-else / v-else-if
1. v-if 基础(移除/创建DOM)
v-if 根据表达式真假,彻底创建或销毁DOM元素(元素不存在于页面中)。
Plaintext
<template>
<div>
<button @click="show = !show">切换显示</button>
<!-- 条件渲染:show为true则显示,false则销毁DOM -->
<h1 v-if="show">v-if 测试文本</h1>
<h2>永久显示的文本</h2>
</div>
</template>
<script>
export default {
data() {
return { show: true };
}
};
</script>
2. v-if + v-else 互斥渲染
v-else 必须紧跟v-if,二者互斥,二选一渲染。
Plaintext
<template>
<div>
<button @click="show = !show">切换</button>
<h1 v-if="show">标签1 显示</h1>
<h2 v-else>标签2 显示</h2>
</div>
</template>
<script>
export default {
data() { return { show: true }; }
};
</script>
二、v-show(CSS 隐藏/显示)
1. 与 v-if 核心区别
| 指令 | 原理 | 适用场景 |
|---|---|---|
| v-if | 动态创建/销毁DOM,切换开销大 | 元素很少切换,一次性显示/隐藏 |
| v-show | 仅切换CSS display: none,DOM始终存在 |
元素频繁切换(弹窗、选项卡) |
代码示例
Plaintext
<template>
<div>
<button @click="show = !show">切换</button>
<!-- v-show:DOM始终存在,仅隐藏 -->
<div v-show="show">
<img src="图片地址" alt="图片">
</div>
</div>
</template>
<script>
export default {
data() { return { show: true }; }
};
</script>
三、列表渲染 v-for
1. 作用
遍历数组/对象,批量渲染列表,Vue 3 强制添加 :key(用于DOM节点标识,提升渲染效率)。
2. 基础语法
Plaintext
<!-- 遍历数组:item 为当前项,index 为索引 -->
<li v-for="(item, index) in 数组" :key="index">{{ item }}</li>
3. 完整案例(动态添加列表)
Plaintext
<template>
<div>
<!-- 输入框:回车添加内容到列表 -->
<input
type="text"
v-model="inputVal"
@keyup.enter="addItem"
placeholder="输入水果,按回车添加"
>
<!-- 数组有内容才显示标题 -->
<h1 v-if="fruitList.length > 0">水果列表</h1>
<!-- 列表渲染 -->
<ul>
<li v-for="(fruit, idx) in fruitList" :key="idx">
{{ fruit }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
inputVal: "",
fruitList: [] // 水果数组
};
},
methods: {
addItem() {
// 去除首尾空格,非空才添加
if(this.inputVal.trim()){
this.fruitList.push(this.inputVal.trim());
this.inputVal = ""; // 清空输入框
}
}
}
};
</script>
四、Vue 过渡 & 动画 <transition>
Vue 内置 <transition> 组件,为元素入场、出场添加过渡动画,无需复杂原生动画代码。
过渡类名规则(name="xxx")
Vue 自动生成6个过渡类名,前缀为name值:
-
xxx-enter:入场起始状态 -
xxx-enter-active:入场动画过程(设置过渡时长、动画曲线) -
xxx-enter-to:入场结束状态 -
xxx-leave:出场起始状态 -
xxx-leave-active:出场动画过程 -
xxx-leave-to:出场结束状态
1. 淡入淡出过渡(Fade)
Plaintext
<template>
<div>
<button @click="show = !show">淡入淡出</button>
<!-- 过渡组件,name="fade" 定义类名前缀 -->
<transition name="fade">
<p v-show="show">淡入淡出动画文本</p>
</transition>
</div>
</template>
<script>
export default {
data() { return { show: true }; }
};
</script>
<style scoped>
/* 入场/出场 动画过程:过渡时长3秒 */
.fade-enter-active,
.fade-leave-active {
transition: opacity 3s;
}
/* 入场起始、出场结束:透明度0(隐藏) */
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>
2. 位移动画(ShiftX 横向滑动)
Plaintext
<template>
<div>
<button @click="show = !show">滑动动画</button>
<transition name="shiftx">
<div v-show="show">
<img src="图片地址" width="100">
</div>
</transition>
</div>
</template>
<script>
export default {
data() { return { show: true }; }
};
</script>
<style scoped>
.shiftx-enter-active,
.shiftx-leave-active {
transition: all 2s ease-in-out;
}
/* 入场从右侧100px开始,透明度0 */
.shiftx-enter,
.shiftx-leave-to {
transform: translateX(100px);
opacity: 0;
}
</style>
3. 帧动画(Rotate 旋转)
结合CSS @keyframes 实现复杂帧动画:
Plaintext
<template>
<div>
<button @click="show = !show">旋转动画</button>
<transition name="rotate">
<img v-show="show" src="图片地址" width="100">
</transition>
</div>
</template>
<script>
export default {
data() { return { show: true }; }
};
</script>
<style scoped>
/* 入场动画 */
.rotate-enter-active {
animation: rotateIn 2s;
}
/* 出场动画(反向执行) */
.rotate-leave-active {
animation: rotateIn 2s reverse;
}
/* 定义旋转帧动画 */
@keyframes rotateIn {
0% { transform: rotateX(0deg); opacity: 0; }
100% { transform: rotateX(360deg); opacity: 1; }
}
</style>
4. 自定义过渡类(集成 Animate.css)
使用enter-active-class/leave-active-class 引入第三方动画库(如Animate.css),无需手写动画:
Plaintext
<template>
<div>
<button @click="show = !show">第三方动画</button>
<!-- 自定义过渡类,绑定Animate.css动画类名 -->
<transition
enter-active-class="animate__animated animate__swing"
leave-active-class="animate__animated animate__bounceOut"
>
<p v-if="show">第三方动画效果</p>
</transition>
</div>
</template>
<script>
export default {
data() { return { show: true }; }
};
</script>