引言
想让网页“活”起来?Vue 就像一位魔法指挥家,只需几行代码,就能让数据跳舞、按钮说话、列表自动排队!本文带你 Vue 学习实验室,从一行插值到复杂事件修饰符,拆解9个真实组件,手把手揭开 Vue 3 的神秘面纱——无需魔法杖,只需一颗好奇的心!
本文将结合多个 Vue 3 单文件组件(SFC)的完整代码,系统讲解 Vue 的核心语法和常用功能,包括 文本插值、属性绑定、条件渲染、列表遍历、双向数据绑定、事件处理、修饰符 等。
一、文本插值与属性绑定(Test1.vue)
<script setup>
// 定义变量
const msg = 'hello vue'
// 变量的值是html代码
const msg2 = '<button>点击我</button>'
const ida = 'd1'
const obj = {
id: 'd2',
class: 'c',
style: 'color: green;'
}
</script>
<template>
<!-- 双大括号可以调用js中的变量 -->
<div>{{ msg }}</div>
<!-- 双大括号不能调用html标签,需要使用v-html指令 -->
<div>{{ msg2 }}</div>
<!-- 如果希望使用html标签,需要使用v-html指令 -->
<div v-html="msg2"></div>v
<div v-bind:id="ida">属性绑定</div>
<div :id="ida">属性绑定的缩写,不用写v-bind</div>
<!-- 如果希望给一个标签绑定多个属性,则属性形成一个对象即可 -->
<div v-bind="obj">{{msg}}</div>
</template>
<style>
#d1 {
color: red;
}
.c {
font-size: 30px;
}
</style>
讲解:
-
{{ }}插值语法:用于在模板中动态显示 JavaScript 表达式的值。例如{{ msg }}会渲染为hello vue。 -
v-html指令:用于渲染包含 HTML 标签的字符串。注意:存在 XSS 风险,仅用于可信内容。 -
v-bind属性绑定:- 完整写法:
v-bind:id="ida" - 缩写:
:id="ida" - 对象批量绑定:
v-bind="obj"会将obj中的每个键值对作为 DOM 属性绑定(如id="d2"、class="c"、内联样式等)。
- 完整写法:
-
响应式无关:此处变量未使用
ref(),因此不具备响应性(但<script setup>中若配合模板使用,Vue 会自动追踪依赖,实际仍可更新;不过推荐显式使用ref保证一致性)。
二、条件渲染(Test2.vue)
<style></style>
<template>
<h2>条件指令学习</h2>
<!-- 条件指令 v-if v-else-if v-else -->
<div v-if="msg==='A'"> A </div>
<div v-else-if="msg==='B'"> B </div>
<div v-else> 既不是A也不是B </div>
<button @click="fun1"> 切换 </button>
<!-- 显示隐藏指令 v-show ,控制元素的显现和隐藏,元素不会消失只是改变样式-->
<div v-show="msg==='A'"> 我是A </div>
</template>
<script setup>
var msg = 'B'
</script>
⚠️ 注意:此代码中
fun1函数未定义,实际运行会报错。应补充如下逻辑,此处只做示范用
讲解:
-
v-if / v-else-if / v-else:- 条件性渲染:根据表达式真假决定是否创建/销毁 DOM 元素。
- 适用于切换频率低的场景。
-
v-show:- 通过设置
display: none控制显隐,DOM 始终存在。 - 适用于频繁切换的场景。
- 通过设置
-
关键区别:
v-if是“真正的条件渲染”,有更高的切换开销;v-show有更高的初始渲染开销,但切换更快。
三、列表渲染(Test3.vue)
<style>
h3 {color: red;}
h4 {color: green;}
#name {color: blue;}
#id {color: pink;}
</style>
<template>
<h3>列表学习</h3>
<ul>
<h4>遍历数组</h4>
<li v-for="stu in arr">
姓名:{{stu.name}},学号:{{stu.id}}
</li>
</ul>
<ul>
<h4>遍历数组的同时获取索引</h4>
<li v-for="(value,index) in names">
{{index + 1}} . {{value}}
</li>
</ul>
<ul>
<h4>遍历对象数组</h4>
<li v-for="value in user">
{{value}}
</li>
</ul>
<ul>
<h4>遍历对象数组的同时获取属性名和属性值</h4>
<li v-for="(value,key) in user">
{{key}} : {{value}}
</li>
</ul>
<ul>
<h4>遍历对象数组的同时获取属性名、属性值和索引</h4>
<li v-for="(value,key,index) in user">
{{ index+1 }} . {{ key }} : {{ value }}
</li>
</ul>
<ul>
<h4>给每个属性写不同的样式</h4>
<template v-for="stu in arr" >
<li id="name">{{stu.name}}</li>
<li id="id">{{stu.id}}</li>
</template>
</ul>
<ul>
<h4>根据属性值判断是否显示</h4>
<li v-for="attr in user">
{{ attr }}
</li>
<li v-if="user.isVIP">VIP:{{user.name}}</li>
<li v-else>普通用户:{{user.name}}</li>
</ul>
</template>
<script setup>
const arr = [
{ name:'Agiao', id:'2023213413', },
{ name:'李四', id:'2023213414', },
{ name:'王五', id:'2023213415', }
]
const names = ['Agiao','李四','王五']
const user = {
name:'Agiao',
password:'123456',
gender:'女',
isVIP:true
}
</script>
讲解:
-
v-for遍历数组:(item, index) in items:item是元素,index是下标(从 0 开始)。
-
v-for遍历对象:(value, key, index) in object:依次获取值、键名、索引。
-
<template v-for>:- 渲染多个元素而不引入额外 DOM 节点(类似 React 的 Fragment)。
-
注意事项:
- 遍历对象时,顺序由
Object.keys()决定(ES2015+ 保证插入顺序)。 - 不应使用
id作为重复元素的 ID(如#name多次出现),这违反 HTML 规范。应改用class或动态:id。
- 遍历对象时,顺序由
四、双向数据绑定(Input1.vue)
<style setup>
h2 { color: red; }
.input-box{ width: 300px; height: 100px; }
</style>
<script setup>
import { ref } from 'vue'
const message = ref("hello vue")
const selected = ref('男')
const selectedColors = ref(['红色'])
const yes = ref('同意协议')
const no = ref('不同意协议')
const checked = ref(yes.value)
const selectedOption = ref('')
const selectedOption1 = ref('')
const city = [
{text: '北京',value: 'bj'},
{text: '杭州',value: 'hz'},
{text: '武汉',value: 'wh'},
{text: '深圳',value: 'sz'},
]
</script>
<template>
<h2>双向数据绑定学习</h2>
<p>文本框的值是:{{ message }}</p>
<div><input class="input-box" type="text" v-model="message" placeholder="请输入内容"></div>
<div><textarea class="input-box" v-model="message" placeholder="请输入多行内容"></textarea></div>
<p>你的选择是:{{ selected }}</p>
<input type="radio" v-model="selected" name="gender" value="男"> 男
<input type="radio" v-model="selected" name="gender" value="女"> 女
<p>你喜欢的颜色是:{{ selectedColors }}</p>
<input type="checkbox" v-model="selectedColors" value="红色"> 红色
<input type="checkbox" v-model="selectedColors" value="绿色"> 绿色
<input type="checkbox" v-model="selectedColors" value="蓝色"> 蓝色
<ul>
<li v-for="color in selectedColors">{{ color }}</li>
</ul>
<p> 是否同意协议:{{ checked }}
<input type="checkbox" v-model="checked" :true-value="yes" :false-value="no"> {{ checked }}
</p>
<p>
你的工作地点是:
<select v-model="selectedOption">
<option value="北京">北京</option>
<option value="杭州">杭州</option>
<option value="武汉">武汉</option>
<option value="深圳">深圳</option>
</select>
你选择的是:{{ selectedOption }}
</p>
<p>
你的工作地点是:
<select v-model="selectedOption1">
<option v-for="item in city" :value="item.value">{{ item.text }}</option>
</select>
你选择的是:{{ selectedOption1 }}
</p>
</template>
讲解:
-
v-model实现双向绑定:- 自动同步表单控件的值与响应式变量。
-
不同类型表单元素的绑定行为:
-
文本框/文本域:绑定
value属性和input事件。 -
单选按钮:
v-model的值等于被选中按钮的value。 -
复选框:
- 单个:绑定布尔值;
- 多个:绑定数组,包含所有被选中的
value。
-
下拉选择框:绑定选中项的
value。
-
-
true-value/false-value:- 自定义复选框在勾选/未勾选时的值(需用
:绑定响应式变量)。
- 自定义复选框在勾选/未勾选时的值(需用
五、v-model 修饰符(Input2.vue)
<style>
h2{color: red;}
input{ height: 30px; width: 300px; }
</style>
<script setup>
import { ref } from 'vue'
const msglazy = ref('')
const msgtrim = ref('')
const msgnumber = ref('')
</script>
<template>
<h2>修饰符学习组件 lazy trim number</h2>
<p>lazy: {{ msglazy }}</p>
<input type="text" v-model.lazy="msglazy" placeholder="请输入内容lazy">
<p>trim: {{ msgtrim }}</p>
<input type="text" v-model.trim="msgtrim" placeholder="请输入内容trim">
<p>number: {{ msgnumber }}</p>
<input type="text" v-model.number="msgnumber" placeholder="请输入内容number">
</template>
讲解:
-
.lazy:将input事件改为change事件(失焦时才更新)。 -
.trim:自动去除输入首尾空格。 -
.number:- 尝试将输入转为数字(使用
parseFloat); - 若无法转换(如
"abc"),则保留原字符串; - 若部分可转(如
"123abc"),则返回123。
- 尝试将输入转为数字(使用
六、事件处理与修饰符(Fun1.vue & Fun2.vue)
Fun1.vue:基础事件
<style> h1 { color: red; }</style>
<template>
<h1>函数学习组件</h1>
<button v-on:click="count++">自增</button>
<p>v-on当前计数:{{count}}</p>
<button @click="count++">自增</button>
<p>@当前计数:{{count}}</p>
<button @click="add()">自增</button>
<button @click="add">方法事件自增</button>
</template>
<script setup>
import { ref } from 'vue';
const count = ref(0)
function add() {
count.value++
}
</script>
- 内联处理器:
@click="count++",适合简单逻辑。 - 方法处理器:
@click="add",适合复杂逻辑(注意:add()与add在无参时效果相同)。 ref响应式:必须通过.value修改(但在模板中可直接使用count)。
Fun2.vue:事件修饰符
<!-- 片段 -->
<button @click.once="fun1">事件修饰符once,事件只触发一次</button>
<div @contextmenu.prevent="fun1">禁止右键菜单</div>
<div @contextmenu="fun2">阻止默认行为(需手动调用 preventDefault)</div>
.once:事件只触发一次。.prevent:自动调用event.preventDefault()。.stop:阻止事件冒泡(示例中未启用,但已注释说明)。
七、按键与系统修饰符(Fun3.vue)
<textarea
@keydown.esc="clearText"
@keydown.up="up"
@keydown.down="down"
@keydown.left="left"
@keydown.right="right">
</textarea>
<div id="div2" @click.ctrl="fun1">按 Ctrl + 点击变黄</div>
- 按键修饰符:
.enter、.esc、.up等,简化键盘事件判断。 - 系统修饰符:
.ctrl、.alt、.shift、.meta,用于组合键。 - 注意:代码中
window.onkeydown使用了错误的KeyCode(应为keyCode或code),且逻辑与局部函数重复,实际应统一处理。
八、自定义指令(HighLight.vue)
<!-- 当前代码中 v-highLight 未定义,故无效 -->
<div v-highLight>这是一个div,会被高亮显示</div>
- 自定义指令:可用于封装 DOM 操作(如聚焦、高亮)。
- 正确做法:取消注释
const vHighLight = { mounted(el) { ... } },或全局注册。
结语
本文通过 9 个真实组件代码,全面覆盖了 Vue 3 的核心语法:
| 功能 | 对应文件 |
|---|---|
| 文本插值、属性绑定 | Test1.vue |
| 条件渲染 | Test2.vue |
| 列表渲染 | Test3.vue |
| 双向绑定(基础) | Input1.vue |
| v-model 修饰符 | Input2.vue |
| 事件处理 | Fun1.vue |
| 事件修饰符 | Fun2.vue |
| 按键/系统修饰符 | Fun3.vue |
| 自定义指令(待完善) | HighLight.vue |
Vue 的魅力,不在于炫技,而在于用最简洁的语法解决最真实的交互问题。通过这组由浅入深的组件实践,我们不仅掌握了指令、绑定与响应式的核心逻辑,更体会到“声明式开发”的优雅与高效。愿你在构建下一个应用时,也能像这些代码一样:清晰、灵动、恰到好处。
完整项目仓库:Vue-pro: Vue学习——Gitee