Vue.js 2.x笔记:基本语法(2)
欢迎来到 Vue.js 2.x 系列笔记的第二部分!在第一部分中,我们学习了 Vue 实例的创建、数据绑定(如文本插值 {{ }}、v-bind 指令)、条件渲染(v-if/v-else)等基础语法。本文作为续篇,将深入讲解 Vue.js 2.x 中更核心的基础语法,包括事件处理、表单输入绑定、列表渲染、计算属性与侦听器以及类与样式绑定。这些内容是构建交互式 Vue 应用的基石,掌握它们将帮助你更高效地开发响应式界面。
目录#
- 事件处理(v-on)
- 基本用法与简写
- 事件修饰符
- 按键修饰符
- 实践与最佳实践
- 表单输入绑定(v-model)
- 基础用法
- 不同输入类型的绑定
- v-model 修饰符
- 实践与最佳实践
- 列表渲染(v-for)
- 遍历数组与对象
- 维护状态:
:key属性 - 数组更新检测
- 实践与最佳实践
- 计算属性与侦听器
- 计算属性(Computed)
- 侦听器(Watch)
- 计算属性 vs 侦听器
- 实践与最佳实践
- 类与样式绑定
- 绑定 HTML 类
- 绑定内联样式
- 实践与最佳实践
- 总结
- 参考资料
1. 事件处理(v-on)#
在 Vue 中,事件处理通过 v-on 指令实现,用于监听 DOM 事件(如点击、输入、提交等)并触发相应的方法。
1.1 基本用法与简写#
语法:
v-on:事件名="方法名" 或简写为 @事件名="方法名"。
示例:
<div id="app">
<!-- 点击按钮触发 handleClick 方法 -->
<button v-on:click="handleClick">点击我</button>
<!-- 简写形式 -->
<button @click="handleClick">点击我(简写)</button>
</div>
<script>
new Vue({
el: '#app',
methods: {
handleClick() {
alert('按钮被点击了!');
}
}
});
</script>内联表达式:也可直接在指令中写简单表达式(不推荐复杂逻辑,建议抽离为方法):
<button @click="count += 1">计数器: {{ count }}</button>1.2 事件修饰符#
DOM 事件有默认行为(如表单提交刷新页面、链接跳转)或冒泡机制,Vue 提供了事件修饰符简化这些操作,无需手动调用 event.preventDefault() 或 event.stopPropagation()。
常用修饰符:
.stop:阻止事件冒泡(event.stopPropagation())。.prevent:阻止默认行为(event.preventDefault())。.once:事件仅触发一次。.self:仅当事件在元素本身触发时才执行(排除子元素冒泡)。
示例:
<!-- 阻止表单默认提交行为 -->
<form @submit.prevent="handleSubmit">
<button type="submit">提交</button>
</form>
<!-- 阻止事件冒泡 -->
<div @click="parentClick">
<button @click.stop="childClick">点击子元素</button>
</div>
<!-- 事件仅触发一次 -->
<button @click.once="handleOnce">只触发一次</button>1.3 按键修饰符#
监听键盘事件时,可通过按键修饰符指定触发事件的按键(如 Enter、Esc)。
常用按键修饰符:
.enter:Enter 键。.tab:Tab 键(需配合keydown事件)。.esc:Esc 键。.space:空格键。- 自定义按键码:通过
Vue.config.keyCodes定义(Vue 2.x 特性)。
示例:
<!-- 按下 Enter 键触发提交 -->
<input @keyup.enter="submitForm" placeholder="按 Enter 提交">
<!-- 按下 Esc 键清空输入 -->
<input @keyup.esc="clearInput" v-model="inputValue">1.4 实践与最佳实践#
- 方法命名规范:事件处理方法建议以
handle开头(如handleSubmit、handleClick),明确其用途。 - 避免内联复杂逻辑:内联表达式仅用于简单操作(如
count += 1),复杂逻辑应抽离为 methods 中的方法,提高可读性。 - 优先使用事件修饰符:代替手动调用
event.preventDefault()等,代码更简洁。 - 传递事件对象:如需访问原生事件对象,可在方法中传入
$event:<button @click="handleClick($event, '参数')">点击</button>methods: { handleClick(event, param) { console.log(event.target, param); // 输出事件目标和参数 } }
2. 表单输入绑定(v-model)#
v-model 是 Vue 提供的双向数据绑定指令,用于在表单元素(如输入框、复选框、下拉框)与 Vue 实例的 data 之间建立关联:用户输入更新数据,数据变化同步更新视图。
2.1 基础用法#
语法:
v-model="data属性名"
示例:
<div id="app">
<input v-model="message" placeholder="输入内容">
<p>你输入的是:{{ message }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
message: ''
}
});
</script>2.2 不同输入类型的绑定#
v-model 可适配不同表单元素,行为略有差异:
2.2.1 文本框(text)与多行文本框(textarea)#
- 绑定字符串,输入内容实时同步。
<!-- 单行文本 -->
<input type="text" v-model="username">
<!-- 多行文本(无需使用 {{ }} 插值,v-model 直接绑定) -->
<textarea v-model="description"></textarea>2.2.2 复选框(checkbox)#
- 单个复选框:绑定布尔值(
true/false)。 - 多个复选框:绑定数组,选中的值会加入数组。
<!-- 单个复选框 -->
<input type="checkbox" v-model="agree"> 同意协议({{ agree }})
<!-- 多个复选框(值为数组) -->
<div>
<input type="checkbox" v-model="hobbies" value="reading"> 阅读
<input type="checkbox" v-model="hobbies" value="sports"> 运动
<input type="checkbox" v-model="hobbies" value="coding"> 编程
<p>爱好:{{ hobbies }}</p> <!-- 选中的值组成数组,如 ["reading", "coding"] -->
</div>2.2.3 单选框(radio)#
- 绑定单个值,选中的
value会赋给数据属性。
<div>
<input type="radio" v-model="gender" value="male"> 男
<input type="radio" v-model="gender" value="female"> 女
<p>性别:{{ gender }}</p> <!-- 选中的值,如 "male" -->
</div>2.2.4 下拉框(select)#
- 单选:绑定单个值;多选:绑定数组(需添加
multiple属性)。
<!-- 单选下拉框 -->
<select v-model="city">
<option value="">请选择城市</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
</select>
<p>城市:{{ city }}</p>
<!-- 多选下拉框(按住 Ctrl 选择多个) -->
<select v-model="cities" multiple>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="guangzhou">广州</option>
</select>
<p>选中城市:{{ cities }}</p> <!-- 数组,如 ["beijing", "guangzhou"] -->2.3 v-model 修饰符#
v-model 提供修饰符优化数据处理:
-
.lazy:默认v-model在input事件中同步数据,.lazy改为在change事件(如失焦或回车)时同步。<input v-model.lazy="message"> <!-- 失焦后才更新 message --> -
.number:自动将输入值转为数字(若无法转为数字则保留原始值)。<input v-model.number="age" type="number"> <!-- age 会被转为 Number 类型 --> -
.trim:自动去除输入值首尾的空格。<input v-model.trim="username"> <!-- 输入 " Tom " 会变为 "Tom" -->
2.4 实践与最佳实践#
- 表单验证:结合
v-model与计算属性/侦听器实现实时验证(如检查用户名长度、密码强度)。 - 初始值匹配:确保
v-model绑定的数据初始值类型与表单元素匹配(如复选框数组初始值应为[],单选框初始值应为字符串)。 - 避免过度使用 v-model:对于复杂表单,可考虑拆分组件或使用状态管理(如 Vuex),避免单个实例数据过于臃肿。
3. 列表渲染(v-for)#
v-for 指令用于基于数组或对象渲染列表,语法类似 JavaScript 的 for...in 循环。
3.1 遍历数组与对象#
3.1.1 遍历数组#
语法:v-for="(item, index) in items",其中 item 是数组元素,index 是索引(可选)。
<div id="app">
<ul>
<li v-for="(item, index) in fruits" :key="item.id">
{{ index + 1 }}. {{ item.name }} - 价格:{{ item.price }}元
</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
fruits: [
{ id: 1, name: '苹果', price: 5 },
{ id: 2, name: '香蕉', price: 3 },
{ id: 3, name: '橙子', price: 4 }
]
}
});
</script>3.1.2 遍历对象#
语法:v-for="(value, key, index) in object",value 是属性值,key 是属性名,index 是索引(可选)。
<div v-for="(value, key) in user" :key="key">
{{ key }}: {{ value }}
</div>
<script>
data: {
user: { name: '张三', age: 25, gender: '男' }
}
</script>
<!-- 输出:
name: 张三
age: 25
gender: 男
-->3.2 维护状态::key 属性#
Vue 在更新使用 v-for 渲染的列表时,默认使用“就地复用”策略(即不重新创建 DOM 元素,仅更新内容)。为确保列表项的唯一性和正确的 DOM 复用,必须为 v-for 提供 :key 属性,值需为唯一标识(如 ID)。
注意:
- 避免使用
index作为:key(若数组排序或过滤,index会变化,导致 DOM 复用错误)。 :key的值需为字符串或数字,且在列表中唯一。
正确示例:
<li v-for="item in fruits" :key="item.id">...</li> <!-- 使用唯一 ID 作为 key -->3.3 数组更新检测#
Vue 能够检测数组的变更方法并触发视图更新,这些方法包括:
push():添加元素到末尾pop():删除末尾元素shift():删除第一个元素unshift():添加元素到开头splice():修改/删除/添加元素(splice(index, deleteCount, ...items))sort():排序reverse():反转
非响应式操作:直接修改数组索引或长度(如 arr[0] = 'new'、arr.length = 0),Vue 无法检测。需使用 Vue.set(arr, index, value) 或 splice 替代:
// 错误(非响应式)
this.fruits[0] = { id: 1, name: '红苹果', price: 6 };
// 正确(响应式)
Vue.set(this.fruits, 0, { id: 1, name: '红苹果', price: 6 });
// 或
this.fruits.splice(0, 1, { id: 1, name: '红苹果', price: 6 });3.4 实践与最佳实践#
- 始终使用
:key:确保列表项的唯一性,避免渲染错误。 - 避免在
v-for中使用v-if:两者优先级冲突(v-for比v-if优先级高),如需条件渲染列表项,可先通过计算属性过滤数组。computed: { filteredFruits() { return this.fruits.filter(item => item.price < 5); // 过滤价格 <5 的水果 } } - 长列表优化:对于大数据列表,考虑使用虚拟滚动(如
vue-virtual-scroller)减少 DOM 节点数量。
4. 计算属性与侦听器#
在 Vue 中,处理数据逻辑时,常用计算属性(Computed) 和侦听器(Watch)。两者用途不同,但都用于响应数据变化。
4.1 计算属性(Computed)#
定义:基于现有数据派生新数据,类似于“动态属性”,依赖数据变化时自动更新。
语法:在 Vue 实例的 computed 选项中定义,返回计算后的值。
示例:计算购物车总价
<div id="app">
<p>商品总价:{{ totalPrice }}元</p>
</div>
<script>
new Vue({
el: '#app',
data: {
cart: [
{ name: '商品A', price: 100, quantity: 2 },
{ name: '商品B', price: 50, quantity: 3 }
]
},
computed: {
totalPrice() {
// 计算总价:价格 × 数量 之和
return this.cart.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
}
});
</script>特点:
- 缓存性:计算属性会缓存结果,依赖数据未变化时,多次访问不会重复计算(提升性能)。
- getter 与 setter:默认是 getter,可定义 setter 实现双向绑定:
computed: { fullName: { get() { return this.firstName + ' ' + this.lastName; }, set(newValue) { const [first, last] = newValue.split(' '); this.firstName = first; this.lastName = last; } } }
4.2 侦听器(Watch)#
定义:监听指定数据的变化,触发自定义逻辑(如异步操作、复杂数据处理)。
语法:在 Vue 实例的 watch 选项中定义,键是监听的数据名,值是处理函数。
示例:监听搜索关键词变化并调用 API
<div id="app">
<input v-model="searchQuery" placeholder="搜索...">
</div>
<script>
new Vue({
el: '#app',
data: {
searchQuery: '',
searchResult: []
},
watch: {
// 监听 searchQuery 的变化
searchQuery(newVal, oldVal) {
// 防抖:300ms 内输入停止后再调用 API
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.fetchSearchResult(newVal);
}, 300);
}
},
methods: {
fetchSearchResult(query) {
// 调用 API 获取搜索结果
console.log('搜索:', query);
// this.searchResult = 接口返回数据;
}
}
});
</script>高级选项:
deep: true:深度监听对象内部属性变化(默认仅监听引用变化)。watch: { user: { handler(newVal) { console.log('用户信息变化:', newVal); }, deep: true // 监听 user 对象的所有属性 } }immediate: true:初始化时立即执行一次处理函数。
4.3 计算属性 vs 侦听器#
| 场景 | 计算属性(Computed) | 侦听器(Watch) |
|---|---|---|
| 用途 | 派生数据(同步、简单逻辑) | 复杂逻辑(异步操作、副作用) |
| 缓存 | 有(依赖不变则不重新计算) | 无(每次数据变化都执行) |
| 写法 | 函数返回值(或 getter/setter) | 回调函数(接收新/旧值) |
最佳实践:
- 优先使用计算属性处理同步、简单的派生数据(如过滤列表、格式化文本)。
- 使用侦听器处理异步操作(如 API 请求)或复杂副作用(如操作 DOM、定时器)。
5. 类与样式绑定#
Vue 允许通过 v-bind 动态绑定 HTML 类(class)和内联样式(style),实现样式的条件化或动态化。
5.1 绑定 HTML 类#
5.1.1 对象语法#
通过对象控制类的“存在与否”(值为 true 则添加类,false 则移除)。
<div :class="{ active: isActive, 'text-danger': hasError }"></div>
<script>
data: {
isActive: true,
hasError: false
}
</script>
<!-- 渲染结果:<div class="active"></div> -->5.1.2 数组语法#
通过数组指定多个类名。
<div :class="[activeClass, errorClass]"></div>
<script>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
</script>
<!-- 渲染结果:<div class="active text-danger"></div> -->5.1.3 混合语法#
数组中嵌套对象,实现条件与固定类的结合。
<div :class="[isActive ? activeClass : '', { 'text-danger': hasError }]"></div>5.2 绑定内联样式#
5.2.1 对象语法#
直接绑定样式对象,键是 CSS 属性(可用 camelCase 或 kebab-case,推荐 camelCase)。
<div :style="{ color: textColor, fontSize: fontSize + 'px' }"></div>
<script>
data: {
textColor: 'red',
fontSize: 16
}
</script>
<!-- 渲染结果:<div style="color: red; font-size: 16px;"></div> -->5.2.2 数组语法#
绑定多个样式对象,合并生效。
<div :style="[baseStyle, activeStyle]"></div>
<script>
data: {
baseStyle: { color: 'black', fontSize: '14px' },
activeStyle: { backgroundColor: 'yellow' }
}
</script>5.2.3 自动前缀#
Vue 会自动为某些 CSS 属性添加浏览器前缀(如 transform),无需手动处理兼容性。
5.3 实践与最佳实践#
- 优先使用类绑定:相比内联样式,类绑定更利于维护(将样式写在 CSS 文件中,支持复用和主题切换)。
- 复杂条件逻辑抽离:若类的条件判断复杂,可将逻辑抽离为计算属性:
computed: { classObject() { return { active: this.isActive && !this.error, 'text-danger': this.error && this.error.type === 'fatal' }; } } - 避免过度动态样式:频繁切换的样式(如动画)可使用 CSS 类结合
transition实现,性能优于动态内联样式。
总结#
本文详细介绍了 Vue.js 2.x 的核心基础语法,包括事件处理(v-on)、表单输入绑定(v-model)、列表渲染(v-for)、计算属性与侦听器,以及类与样式绑定。这些内容是 Vue 开发的基石,掌握它们能帮助你构建交互丰富、响应式的前端应用。
建议结合实际项目练习,例如:
- 使用
v-for和v-model实现一个待办事项列表(Todo List)。 - 用计算属性处理数据过滤或格式化。
- 通过事件修饰符优化表单提交和事件冒泡逻辑。