前面我们掌握了 Vue 的基础指令,今天聚焦指令进阶、计算属性、侦听器这三个核心能力,让你真正学会 Vue 的高效开发方式!
一、指令补充:让基础指令更强大
基础指令能满足简单需求,结合修饰符、样式增强后,能应对更复杂的场景。
1. 指令修饰符:简化逻辑的 "快捷键"
指令修饰符是v-on/v-model等指令的 "扩展功能",能减少methods中的冗余代码。
(1)v-on修饰符
.stop:阻止事件冒泡(替代e.stopPropagation()).prevent:阻止默认行为(替代e.preventDefault()).once:事件只触发一次.enter/.esc:按键修饰符(仅触发指定按键的事件)
html
<div id="app">
<!-- .stop:阻止冒泡 -->
<div @click="parentClick" style="padding: 20px; background: #eee;">
父元素
<button @click.stop="childClick">子按钮(点击不触发父事件)</button>
</div>
<!-- .prevent:阻止表单提交默认行为 -->
<form @submit.prevent="handleSubmit">
<button type="submit">提交(不刷新页面)</button>
</form>
<!-- .once:只触发一次 -->
<button @click.once="sayHi">只点一次有效</button>
<!-- .enter:回车触发 -->
<input @keyup.enter="handleEnter" placeholder="按回车触发">
</div>
<script>
new Vue({
el: '#app',
methods: {
parentClick() { alert('父元素被点击') },
childClick() { alert('子按钮被点击') },
handleSubmit() { alert('表单提交了') },
sayHi() { alert('只触发一次') },
handleEnter() { alert('按了回车') }
}
})
</script>
(2)v-model修饰符
.trim:自动去除输入内容的首尾空格.number:自动将输入转为数字类型.lazy:失去焦点 / 按回车时才同步数据(默认是输入时实时同步)
html
<div id="app">
<!-- .trim:去空格 -->
<input v-model.trim="username" placeholder="输入后自动去空格">
<p>用户名:"{{ username }}"</p>
<!-- .number:转数字 -->
<input v-model.number="age" type="number" placeholder="输入数字">
<p>年龄类型:{{ typeof age }}</p> <!-- 输入后是number类型 -->
<!-- .lazy:失去焦点同步 -->
<input v-model.lazy="content" placeholder="失去焦点后同步">
<p>内容:{{ content }}</p>
</div>
<script>
new Vue({
el: '#app',
data: { username: '', age: '', content: '' }
})
</script>
2. v-bind样式操作增强
v-bind绑定class/style时,支持对象、数组语法,能更灵活地控制样式。
(1)class的数组语法:同时添加多个动态类
html
<div id="app">
<!-- 数组语法:结合固定类和动态类 -->
<div
class="base-class"
:class="[activeClass, { redClass: isRed }]"
>
动态class数组语法
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
activeClass: 'active', // 固定动态类
isRed: true // 条件动态类
}
})
</script>
<style>
.base-class { padding: 10px; }
.active { border: 1px solid #000; }
.redClass { color: red; }
</style>
(2)style的对象语法:更简洁的动态样式
html
<div id="app">
<!-- style对象语法:直接绑定样式对象 -->
<div :style="boxStyle">动态style对象</div>
</div>
<script>
new Vue({
el: '#app',
data: {
boxStyle: {
width: '200px',
height: '100px',
backgroundColor: 'lightblue',
fontSize: '16px'
}
}
})
</script>
3. v-model适配其他表单元素
v-model不仅支持输入框,还能适配复选框、单选框、下拉选择器等表单元素。
(1)单选框组
html
<div id="app">
<div>选择性别:</div>
<input type="radio" id="male" value="male" v-model="gender">
<label for="male">男</label>
<input type="radio" id="female" value="female" v-model="gender">
<label for="female">女</label>
<p>选中:{{ gender }}</p>
</div>
<script>
new Vue({
el: '#app',
data: { gender: 'male' } // 默认选中男
})
</script>
(2)复选框组
html
<div id="app">
<div>选择爱好:</div>
<input type="checkbox" id="game" value="game" v-model="hobbies">
<label for="game">游戏</label>
<input type="checkbox" id="reading" value="reading" v-model="hobbies">
<label for="reading">阅读</label>
<input type="checkbox" id="sports" value="sports" v-model="hobbies">
<label for="sports">运动</label>
<p>选中:{{ hobbies }}</p>
</div>
<script>
new Vue({
el: '#app',
data: { hobbies: ['reading'] } // 默认选中阅读
})
</script>
(3)下拉选择器(单选 / 多选)
html
<div id="app">
<!-- 单选下拉框 -->
<select v-model="selectedCity">
<option value="">请选择城市</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
</select>
<p>选中城市:{{ selectedCity }}</p>
<!-- 多选下拉框(加multiple属性) -->
<select v-model="selectedFruits" multiple style="height: 100px;">
<option value="apple">苹果</option>
<option value="banana">香蕉</option>
<option value="orange">橙子</option>
</select>
<p>选中水果:{{ selectedFruits }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
selectedCity: 'beijing', // 默认选中北京
selectedFruits: ['apple'] // 默认选中苹果
}
})
</script>
二、computed 计算属性:高效处理依赖数据
计算属性是基于data中的数据动态计算出的新数据,会缓存结果(依赖不变时不会重复计算),比methods更高效。
1. 基础语法
html
<div id="app">
<p>商品价格:{{ price }} 元</p>
<p>购买数量:{{ count }}</p>
<!-- 计算属性:自动计算总价 -->
<p>总价:{{ totalPrice }} 元</p>
</div>
<script>
new Vue({
el: '#app',
data: { price: 50, count: 2 },
computed: {
// 计算属性:函数形式,返回计算结果
totalPrice() {
return this.price * this.count;
}
}
})
</script>
2. 计算属性 vs 方法:核心区别
computed计算属性:依赖数据不变时,结果会缓存;当作属性使用(不加());依赖数据的动态计算(如总价)methods方法:每次调用都会重新执行;当作方法调用(加());事件处理、复杂逻辑(无缓存)
3. 完整写法(含 get/set)
计算属性默认是 "只读" 的,若需要修改计算属性,可以用get(读取)和set(修改)的完整写法:
html
<div id="app">
<p>姓:{{ firstName }}</p>
<p>名:{{ lastName }}</p>
<p>全名:{{ fullName }}</p>
<!-- 修改计算属性 -->
<input v-model="fullName" placeholder="修改全名">
</div>
<script>
new Vue({
el: '#app',
data: { firstName: '张', lastName: '三' },
computed: {
fullName: {
// get:读取计算属性时执行
get() {
return this.firstName + this.lastName;
},
// set:修改计算属性时执行
set(newValue) {
// 拆分新值为姓和名
this.firstName = newValue[0];
this.lastName = newValue.slice(1);
}
}
}
})
</script>
4. 实战案例:成绩统计
html
<div id="app">
<div>语文:<input v-model.number="chinese"></div>
<div>数学:<input v-model.number="math"></div>
<div>英语:<input v-model.number="english"></div>
<!-- 计算属性:统计总分、平均分 -->
<p>总分:{{ totalScore }}</p>
<p>平均分:{{ averageScore }}</p>
</div>
<script>
new Vue({
el: '#app',
data: { chinese: 80, math: 90, english: 85 },
computed: {
totalScore() {
return this.chinese + this.math + this.english;
},
averageScore() {
return Math.round(this.totalScore / 3); // 四舍五入
}
}
})
</script>
三、watch 侦听器:监听数据变化做联动
侦听器用于监听data或computed中数据的变化,当数据改变时执行自定义逻辑(如请求接口、更新 DOM)。
1. 基础语法
html
<div id="app">
<input v-model="username" placeholder="输入用户名">
</div>
<script>
new Vue({
el: '#app',
data: { username: '' },
watch: {
// 监听username的变化
username(newVal, oldVal) {
console.log(`用户名从${oldVal}变成了${newVal}`);
// 实际场景:可在这里调用接口检测用户名是否重复
// this.checkUsername(newVal);
}
},
methods: {
checkUsername(name) {
// 模拟接口请求
console.log(`检测用户名:${name} 是否可用`);
}
}
})
</script>
2. 完整写法(深度监听 / 立即执行)
对于对象 / 数组的变化,需要开启deep: true(深度监听);若需要初始时立即执行,可设置immediate: true:
html
<div id="app">
<div>用户信息:{{ user.name }},{{ user.age }}岁</div>
<button @click="user.age++">增加年龄</button>
</div>
<script>
new Vue({
el: '#app',
data: {
user: { name: '张三', age: 20 }
},
watch: {
// 监听对象的变化(需深度监听)
user: {
handler(newVal, oldVal) {
console.log(`年龄从${oldVal.age}变成了${newVal.age}`);
},
deep: true, // 深度监听对象内部属性
immediate: true // 初始时立即执行一次
}
}
})
</script>