在 Vue 开发中,表单数据收集、指令使用和生命周期管理是核心基础。掌握这些知识点能让你更高效地构建交互式页面,本文将结合实例详细拆解,帮助你快速上手实战。
一、表单数据收集:v-model 的全面应用
v-model 是 Vue 实现表单双向绑定的核心指令,其收集数据的规则随表单元素类型变化,配合修饰符可满足多样化需求。
1. 输入框类表单(text/password/number)
- 核心逻辑:v-model 直接收集元素的 value 值,用户输入内容即 value 值。
- 常用修饰符:
- trim:自动过滤输入内容首尾的空格,适用于账号、昵称等场景。
- number:将输入的字符串转为有效数字,适用于年龄、金额等数值类输入。
- lazy:失去焦点后再收集数据,减少实时数据更新的性能消耗。
<div id="root">
<form @submit.prevent="submitForm">
账号:<input type="text" v-model.trim="userInfo.a***ount"><br/><br/>
密码:<input type="password" v-model="userInfo.password"><br/><br/>
年龄:<input type="number" v-model.number="userInfo.age"><br/><br/>
<button>提交</button>
</form>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
userInfo:{ a***ount:'', password:'', age:18 }
},
methods: {
submitForm(){ console.log(JSON.stringify(this.userInfo)) }
}
})
</script>
2. 单选按钮(radio)
- 核心要求:必须为每个单选框配置 value 属性,v-model 收集的是选中项的 value 值。
- 注意事项:无需手动设置 name 属性,v-model 会自动实现互斥效果。
<div id="root">
<form @submit.prevent="submitForm">
性别:
男<input type="radio" v-model="userInfo.sex" value="male">
女<input type="radio" v-model="userInfo.sex" value="female">
</form>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{ userInfo:{ sex:'female' } }, // 默认选中女性
methods: { submitForm(){ console.log(this.userInfo) } }
})
</script>
3. 复选框(checkbox)
- 无 value 属性:收集的是布尔值(true = 勾选,false = 未勾选),适用于同意协议等单个勾选场景。
- 有 value 属性:
- 初始值为非数组:收集布尔值(是否勾选)。
- 初始值为数组:收集所有勾选项的 value 值组成的数组,适用于多选项(如爱好选择)。
4. 下拉选择框(select)与文本域(textarea)
- 下拉框:v-model 绑定选中项的 value 值,option 标签需配置 value 属性。
- 文本域:与输入框用法一致,支持 lazy 等修饰符,无需手动设置 rows 属性(Vue 自动适配)。
<div id="root">
<form @submit.prevent="submitForm">
爱好:
学习<input type="checkbox" v-model="userInfo.hobby" value="study">
打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
<br/><br/>
所属校区:
<select v-model="userInfo.city">
<option value="">请选择校区</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
</select>
<br/><br/>
其他信息:<textarea v-model.lazy="userInfo.other"></textarea>
<button>提交</button>
</form>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
userInfo:{ hobby:[], city:'beijing', other:'' }
},
methods: { submitForm(){ console.log(this.userInfo) } }
})
</script>
二、Vue 指令:内置指令与自定义指令
指令是 Vue 操作 DOM 的核心方式,分为内置指令和自定义指令,用于实现页面渲染、DOM 操作等功能。
1. 常用内置指令
- v-text:渲染文本内容,会替换节点原有内容(替代插值语法 {{}},使用较少)。
- v-html:渲染包含 HTML 结构的内容,需注意 XSS 安全风险(仅用于可信内容,禁止用于用户输入)。
- v-cloak:解决网速较慢时页面显示 {{xxx}} 的问题,配合 CSS 使用(
[v-cloak]{display:none})。 - v-once:仅渲染一次,后续数据更新不会重新渲染(适用于静态内容,优化性能)。
- v-pre:跳过节点编译过程,加快 Vue 编译速度(适用于无指令、无插值的纯静态节点)。
2. 自定义指令
当内置指令无法满足需求时,可自定义指令实现特定功能,支持全局注册和局部注册。
核心语法
- 全局注册:
Vue.directive(指令名, 配置对象/回调函数) - 局部注册:在 Vue 实例的 directives 选项中配置
- 注意事项:指令名定义时不加 v-,使用时需加 v-;多单词指令采用 kebab-case 命名(如 v-big-number)。
配置对象常用回调
- bind:指令与元素成功绑定时调用(初始绑定,仅一次)。
- inserted:指令所在元素插入 DOM 时调用(适合操作 DOM 节点,如获取焦点)。
- update:指令所在模板重新解析时调用(数据更新时触发)。
实战案例
需求 1:v-big 指令,将绑定数值放大 10 倍后渲染。需求 2:v-fbind 指令,实现 v-bind 功能 + 输入框默认获取焦点。
<div id="root">
<h2>放大10倍:<span v-big="n"></span></h2>
<input type="text" v-fbind:value="n">
</div>
<script>
Vue.config.productionTip = false
// 全局自定义指令v-big
Vue.directive('big', {
bind(el, binding){ el.innerText = binding.value * 10 },
update(el, binding){ el.innerText = binding.value * 10 }
})
// 全局自定义指令v-fbind
Vue.directive('fbind', {
bind(el, binding){ el.value = binding.value }, // 绑定初始值
inserted(el){ el.focus() }, // 元素插入DOM时获取焦点
update(el, binding){ el.value = binding.value } // 数据更新时同步值
})
new Vue({
el:'#root',
data:{ n:1 }
})
</script>
三、Vue 生命周期:实例的完整生命周期
Vue 实例从创建到销毁的整个过程称为生命周期,每个阶段都有对应的钩子函数,允许开发者在特定时机执行操作。
1. 生命周期核心阶段与钩子函数
| 阶段 | 钩子函数 | 核心作用 |
|---|---|---|
| 实例创建 | beforeCreate | 数据监测、事件初始化前,无法访问 data、methods |
| 实例创建后 | created | 数据、方法配置完成,未挂载 DOM,无法访问 $el |
| 挂载前 | beforeMount | 解析模板生成虚拟 DOM,未插入页面(页面显示原始模板) |
| 挂载后 | mounted | 虚拟 DOM 转为真实 DOM 并插入页面,可操作 DOM(常用) |
| 更新前 | beforeUpdate | 数据更新,真实 DOM 未同步(数据新、页面旧) |
| 更新后 | updated | 真实 DOM 已同步,可执行依赖 DOM 的操作 |
| 销毁前 | beforeDestroy | 实例仍可用,执行收尾工作(如清除定时器、解绑事件) |
| 销毁后 | destroyed | 实例完全销毁,所有绑定、事件、子实例失效 |
2. 常用钩子函数实战
- mounted:初始化操作(发送 AJAX 请求、启动定时器、绑定自定义事件)。
- beforeDestroy:收尾工作(清除定时器、取消订阅、解绑自定义事件)。
<div id="root">
<h2 :style="{opacity}">Vue生命周期演示</h2>
<button @click="stop">停止渐变</button>
</div>
<script>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{ opacity:1 },
methods:{
stop(){ this.$destroy() } // 销毁Vue实例
},
mounted(){
// 启动定时器,实现渐变效果
this.timer = setInterval(()=>{
this.opacity -= 0.01
if(this.opacity <= 0) this.opacity = 1
},16)
},
beforeDestroy(){
// 销毁前清除定时器,避免内存泄漏
clearInterval(this.timer)
console.log('实例即将销毁,定时器已清除')
}
})
</script>
3. 完整代码案例:透明度渐变与生命周期监控
<!DOCTYPE html>
<html lang="zh-***">
<head>
<meta charset="UTF-8">
<title>Vue生命周期实战</title>
<script src="https://cdn.jsdelivr.***/npm/vue@2/dist/vue.js"></script>
<style>
/* 用于演示v-cloakak解决插值 {{}}闪烁问题(可选) */
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<!-- 绑定透明度样式,实现渐变效果 -->
<h2 :style="{ opacity: opacityValue }">Vue生命周期演示:透明度渐变</h2>
<button @click="opacityValue = 1">重置透明度</button>
<button @click="destroyVm">销毁实例</button>
<p>当前透明度:{{ opacityValue.toFixed(2) }}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
opacityValue: 1 // 透明度初始值(1=完全不透明)
},
methods: {
destroyVm() {
this.$destroy() // 调用Vue实例的销毁方法
}
},
// 1. 实例创建前:数据和事件未初始化
beforeCreate() {
console.log('【beforeCreate】实例创建前');
console.log('数据是否可访问:', this.opacityValue); // undefined
console.log('方法是否可调用:', typeof this.destroyVm); // undefined
},
// 2. 实例创建后:数据和方法初始化完成,未挂载DOM
created() {
console.log('【created】实例创建后');
console.log('数据是否可访问:', this.opacityValue); // 1(可访问)
console.log('方法是否可调用:', typeof this.destroyVm); // function(可调用)
// 此时无法操作DOM($el不存在)
console.log('DOM是否挂载:', this.$el); // undefined
},
// 3. 挂载前:模板解析完成,虚拟DOM生成,未插入页面
beforeMount() {
console.log('【beforeMount】挂载前');
console.log('虚拟DOM是否生成:', this.$el); // 虚拟DOM(未渲染到页面)
console.log('页面中是否有解析后的内容:', document.querySelector('h2').innerText);
// 输出:{{ opacityValue }}(页面仍显示模板语法)
},
// 4. 挂载后:虚拟DOM转为真实DOM,插入页面(常用)
mounted() {
console.log('【mounted】挂载后');
console.log('真实DOM是否生成:', this.$el); // 真实DOM元素
console.log('页面中是否有解析后的内容:', document.querySelector('h2').innerText);
// 输出:Vue生命周期演示:透明度渐变(已渲染)
// 启动定时器,实现透明度渐变(核心业务逻辑)
this.timer = setInterval(() => {
this.opacityValue -= 0.01;
if (this.opacityValue <= 0) this.opacityValue = 1; // 循环渐变
}, 20);
},
// 5. 更新前:数据已更新,真实DOM未同步(数据新,页面旧)
beforeUpdate() {
console.log('【beforeUpdate】更新前');
console.log('数据值:', this.opacityValue.toFixed(2));
console.log('页面值:', document.querySelector('p').innerText.split(':')[1]);
// 数据值与页面值不一致(页面未更新)
},
// 6. 更新后:真实DOM已同步(数据与页面一致)
updated() {
console.log('【updated】更新后');
console.log('数据值:', this.opacityValue.toFixed(2));
console.log('页面值:', document.querySelector('p').innerText.split(':')[1]);
// 数据值与页面值一致(页面已更新)
},
// 7. 销毁前:实例仍可用,执行收尾工作(常用)
beforeDestroy() {
console.log('【beforeDestroy】销毁前');
console.log('实例是否仍可用:', this.opacityValue); // 1(数据仍可访问)
// 清除定时器(避免内存泄漏)
clearInterval(this.timer);
console.log('定时器已清除');
},
// 8. 销毁后:实例完全失效
destroyed() {
console.log('【destroyed】销毁后');
console.log('实例是否仍可用:', this.opacityValue); // 1(数据仍可访问,但修改不会触发更新)
// 尝试修改数据,页面不会更新
this.opacityValue = 0.5;
}
});
</script>
</body>
</html>
案例核心解析:生命周期钩子的执行时机与作用
1. 初始化阶段(创建与挂载)
-
beforeCreate:实例刚被创建,数据监测和事件系统未初始化,无法访问
data和methods。- 用途:几乎不用,可做最早期的准备工作。
-
created:数据和方法初始化完成,但 DOM 未挂载(
$el不存在)。- 用途:适合初始化数据、发送 AJAX 请求(无需操作 DOM 的场景)。
-
beforeMount:模板解析完成,虚拟 DOM 生成,但未渲染到页面,页面仍显示模板语法(如
{{}})。- 用途:可修改数据,但不会触发更新(实际开发中很少用)。
-
mounted:虚拟 DOM 转为真实 DOM 并插入页面,
$el可用。- 用途:最常用的钩子,适合操作 DOM(如初始化插件)、启动定时器、绑定事件等。
2. 运行阶段(数据更新)
-
beforeUpdate:数据发生变化后触发,此时数据是新的,但页面仍是旧的(未同步)。
- 用途:可获取更新前的 DOM 状态。
-
updated:页面已根据新数据更新,数据与 DOM 同步。
- 用途:可执行依赖新 DOM 的操作(如滚动到指定位置),但需避免在此修改数据(可能导致无限循环)。
3. 销毁阶段
-
beforeDestroy:实例即将销毁,仍可访问数据和方法,所有功能正常。
- 用途:最常用的钩子,执行收尾工作(清除定时器、解绑事件、取消订阅等)。
-
destroyed:实例完全销毁,所有事件监听、子实例失效,修改数据不会触发更新。
- 用途:几乎不用,可做最终的资源释放。
关键结论与实战技巧
-
常用钩子:
mounted(初始化操作)和beforeDestroy(收尾工作)是日常开发中使用频率最高的两个钩子。 -
内存泄漏防范:在
beforeDestroy中必须清除定时器、解绑自定义事件等,避免实例销毁后资源仍在占用。 - 销毁后特性:实例销毁后,原生 DOM 事件仍有效(如点击按钮的默认行为),但 Vue 的响应式系统失效(修改数据不会更新页面)。
-
调试技巧:通过
console.log在每个钩子中输出关键信息(如数据、DOM 状态),可直观观察生命周期流转。
3. 生命周期关键说明
- 销毁实例后,自定义事件失效,但原生 DOM 事件仍有效。
- 销毁前操作数据不会触发页面更新(生命周期已停止)。
- 借助 Vue 开发者工具可查看实例是否已销毁。
总结
本文围绕 Vue 核心知识点展开,从表单数据收集的 v-model 使用技巧,到内置 / 自定义指令的实战应用,再到生命周期的完整解析,覆盖了 Vue 开发的基础核心场景。掌握这些知识点后,你可以轻松应对大部分交互式页面开发需求。