一 vm对象的生命周期
代码示例

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="app"> <p ref="p1">{{message}}</p> <input type="text" v-model="message"> </div> <script> var vm = Vue.createApp({ data(){ return { message: "hello", } }, beforeCreate(){ // 当前函数执行时,vm还没有初始化完成。 console.log("beforeCreate>>>", this.$data); console.log("beforeCreate>>>", this.$el); console.log("beforeCreate>>>", this.$refs); }, created(){ // 当前函数执行时,vm对象已经初始化完成 console.log("created>>> $data=", this.$data); // 此时data选项中的数据已经被注入到vm对象中 console.log("created>>> $el=", this.$el); console.log("created>>> $refs=", this.$refs); // 在开发中,我们可以在这个函数中进行初始化数据相关的操作,例如:使用ajax从服务器中读取数据,并赋值给data }, beforeMount(){ // 已经把对应的vue语法的变量替换成了html内容了,但是并没有挂载到el标签的内容中 console.log("beforeMount>>> $el=", this.$el); console.log("beforeMount>>> template=", this.$options.template); console.log("beforeMount>>> $refs=", this.$refs); }, mounted(){ // vue生成的HTML内容已经挂载到了$el属性中 console.log("mounted>>>", this.$el); console.log("mounted>>>", this.$refs); }, beforeUpdate(){ // 变量更新前,data选项中的数据发生了改变,但是没有重新生成虚拟DOM,所以HTML中的变量值没有被同步 console.log("beforeUpdate>>>", this.$data); console.log("beforeUpdate>>>", this.$el.parentElement.innerHTML); // 修改数据前,判断本次修改是否合法?发送ajax, }, updated(){ // 变量更新后,html内容已经与data选项中的数据同步了,因为重新生成了虚拟DOM console.log("updated>>>", this.$el.parentElement.innerHTML); // 修改数据后,发送ajax,同步数据库 } }).mount("#app") </script> </body> </html>
说明
1 2 3 | 在vue使用的过程中,如果要初始化操作,把初始化操作的代码放在 mounted 中执行。 mounted阶段就是在vm对象已经把data数据实现到页面以后。一般页面初始化使用。例如,用户访问页面加载成功以后,就要执行的ajax请求。 另一个就是< strong >created</ strong >,这个阶段就是在vue对象创建以后,mounted之前。把ajax请求后端数据的代码放进 created |
二 选项API
1 过滤器【Vue3.0已淘汰过滤器选项】
Vue3.0已经被淘汰了过滤器这个选项,所以以下使用2.6.11版本来完成代码的编写。
过滤器,是vue允许开发者自定义的文本格式化函数,可以使用在两个地方:输出内容和操作数据中。
1.1 使用Vue.filter进行全局定义
./assets/filter.js
1 2 3 4 5 | // 定义一个全局过滤器,定义在vm对象的外部,提供给整个项目都可以调用。 // Vue.filter("过滤器函数名", 匿名函数); Vue.filter("money", (data)=>{ return `${data.toFixed(2)}元` }) |
1.2 在vm对象中通过filters选项api来局部定义
代码:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./assets/vue@2.7.8.js"></script> <script src="./assets/filter.js"></script> </head> <body> <div id="app"> <p>{{price|money}}</p> <p>{{price|mon}}</p> <p>{{money_format(price)}}</p> </div> <script> var vm = new Vue({ // 相当于vue3.x的 Vue.createApp() el: "#app", // 相当于vue3.x的mount绑定视图方法 data(){ return { // message: "hello, vue2.x", price: 3.55555 } }, methods: { money_format(data){ // 过滤器完全可以被methods选项中定义的函数所代替,所以在vue3.x以后成为了废弃特性 return `¥${data.toFixed(2)}` } }, filters: { // 局部过滤器,是当前vm对象的属性方法存在,所以无法被外界使用 mon(data){ return `¥${data.toFixed(2)}` } } }) </script> </body> </html>
2 计算属性
计算属性,是vue提供给我们开发者用于编写代码时保存计算出新的数据结果的变量。主要通过computed选项进行声明的。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="app"> <input type="text" v-model.number="num1">+ <input type="text" v-model.number="num2">={{result}} </div> <script> var vm = Vue.createApp({ data(){ return{ num1:10, num2:20, } }, computed: { result(){ return this.num1 + this.num2 } } }).mount("#app") </script> </body> </html>
3 侦听属性
侦听属性,可以帮助我们侦听data某个数据的变化,从而做相应的自定义操作。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://unpkg.com/vue@next"></script> <style> input{ outline: none; border: 1px solid #333; } </style> </head> <body> <div id="app"> 账号:<input ref="username" type="text" v-model="username" @blur="check_username"><br> 密码:<input ref="password" type="text" v-model="password"><br> </div> <script> var vm = Vue.createApp({ data(){ return{ username:"", password:"", } }, methods: { check_username(){ console.log("check_username执行了。") } }, watch: { username(new_data, old_data) { console.log(`old_data>>${old_data},new_data>>${new_data}`) let length = this.username.length; if (length > 6 && length < 16) { this.$refs.username.style.border = "1px solid blue"; } else { this.$refs.username.style.border = "1px solid red"; } }, password(new_vuale, old_value) { if (/^\d+$/.test(this.password)) { this.$refs.password.style.block = "1px solid red"; } else { this.$refs.password.style.block = "1px solid blue"; } } }, }).mount("#app") </script> </body> </html>
三 组合API
Vue3.0在原来2.0版本基础上进行升级的时候,进行语法上的扩展与兼容。
选项API的特点:
数据与操作数据的方法是分开在不同的选项中存放的。当一个页面组件中数据多了,方法多了,维护成本会增加
组合API的特点:
提供了一个setup的初始方法和两个声明数据方法ref和derective,可以让我们把数据的声明以及操作数据的方法写到一块的新方法。
1 基本语法声明
响应式变量:
ref函数的作用是用于声明vue的基本数据类型[Number,String,Boolean/undefined/Array等]的响应式变量,可以进行双向数据绑定
reactive 函数的作用是用于声明vue的复杂数据类型[Object]的响应式变量,可以进行双向数据绑定。
代码:

<template> <h2>变量声明</h2> <p>num1={{num1}}</p> <input type="text" v-model="num1"> <hr> <p>num2={{num2}}</p> <input type="text" v-model="num2"> <ul> <li v-for="item in data">{{item}}</li> </ul> {{student_info}}<br> {{student_info.name}}<br> <hr> <h2>修改变量</h2> <button @click="change_data1">修改ref数据</button> <button @click="change_data2">修改reactive数据</button> <hr> <h2>计算属性</h2> <input type="text" size="1" v-model.number="data1"> + <input type="text" v-model.number="data2"> = {{result}} </template> <script setup> import {ref, reactive, watch, onMounted, computed} from "vue"; /** * 声明只读变量 */ let num1 = 10; // 声明一个只读变量,无法在template中进行双向数据绑定 /** * 声明响应式变量 * ref函数的作用就是用于声明vue的基本数据类型[Number,String,Boolean/undefined/Array等]的响应式变量,可以进行双向数据绑定 * reactive 函数的作用就是用于声明vue的复杂数据类型[Object]的响应式变量,可以进行双向数据绑定 */ let num2 = ref(100); let data = ref([ {"id":1, "name": "小明", "age": 11}, {"id":2, "name": "小白", "age": 18}, {"id":3, "name": "小华", "age": 17}, {"id":4, "name": "小绿", "age": 18}, ]); let student_info = reactive({ "id": 1, "name": "小白", "age": 16 }) /** * 修改变量的操作 */ const change_data1 = ()=>{ // 修改ref响应式变量的值,需要通过value来改动 num2.value = 30000; console.log(num2); } const change_data2 = ()=>{ // 修改reactive响应式变量的值,不能修改变量本身,可以修改变量内部的属性,直接赋值即可。 student_info.age = 20; } // 监听属性写法 watch( num2, // 监听ref响应式变量,参数1是一个函数,返回值是被监听的ref变量的value属性 ()=>{ // 值发生改变时自动调用的代码 console.log("num2改变了", num2); } ) watch( student_info, // 监听reactive响应式变量,参数1就是被监听的reactive变量 ()=>{ console.log("student_info改变了", student_info) } ) /** * 钩子方法 */ // created 钩子,vue初始化完成时自动自动的。但是在组合API中时没有created钩子的 // 原因开发者在 <script setup>标签中缩写的所有所有代码,默认都是在created钩子中执行的。 console.log("created执行了,此时vue刚完成初始化,还是渲染template") // mounted钩子方法,在组合API中叫onMounted onMounted(()=>{ // 视图被渲染以后,执行代码。 console.log("Mounted执行了,此时vue已经渲染了html内容"); }) /** * computed 计算属性 */ let data1 = ref(10); let data2 = ref(20); let result = computed(()=>{ return data1.value+data2.value; }); </script> <style scoped> </style>

<script setup> import GroupApi from "./views/GroupApi.vue" </script> <template> <GroupApi></GroupApi> </template> <style scoped> </style>
2 参数传递
传递方向 | 描述 | 代码 |
父传子 |
在父组件中,传递数据需要通过组件标签名的属性进行传递, 而子组件中,通过defineProps接受父组件传递过来的数据。 |
![]() <template> <hi>User父组件</hi> <title>User</title> <input type="text" v-model="str_data"> <input type="text" v-model.number="num_data"> <!-- 传递值--> <Info :str_message="str_data" :num_message="num_data" :obj_data="obj_data" @num_change="get_num" ></Info> </template> <script setup> import {reactive,ref} from "vue"; // 引入 import Info from "./Info.vue"; let str_data=ref("hello world"); let num_data=ref(10); let obj_data=reactive({ id:1, name:"小明", age:16, }) const get_num = (data)=>{ console.log("父组件中接收数据data=", data.value); } </script> <style scoped> </style>
![]() <template> <p>Info子组件</p> <p>子组件中接收来自父组件的数据</p> <p>{{props.str_message}}</p> <p>{{props.num_message}}</p> <p>{{props.obj_data}}</p> num=<input type="text" v-model="num"> </template> <script setup> import {defineProps,ref,watch} from "vue" // 使用defineProps来接收父组件的数据 const props = defineProps({ str_message:{ type:String, default:"没有数据" }, num_message:{ type:Number, default:0, }, obj_data:Object }) // 注册事件源 const emits = defineEmits(['num_change']) let num = ref(10); watch( num, ()=>{ console.log(num.value); emits("num_change", num) } ) </script> <style scoped> </style> |
子传父 |
在子组件中通过defineEmits先声明要注册的事件源,然后通过defineEmits的返回值emits进行调用事件源进行参数传递, 在父组件中,直接声明方法绑定到子组件标签名中即可。 |
四 指令和事件修饰符
4.1 常用指令
指令 | 描述 |
v-model.trim | 用于去除字符串两边的空白字符,常用于密码 |
v-model.lazy | 用于减少触发watch侦听选项的频率,从原来的input输入事件的侦听切换成了change值改变事件的监听 |
v-model.number | 表示把变量作为数值来进行转换提取,能转的都会转换 |
代码示例

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="app"> <input type="password" v-model.trim="password"><br> <input type="text" v-model.lazy="mobile"><br> <input type="text" v-model.number="num">+500=<span>{{ num+500 }}</span> </div> <script> const vm=Vue.createApp({ data(){ return{ passsword: " ", mobile:"", num:0, } } , watch:{ passsword(){ console.log(this.passsword); }, mobile(){ console.log("发送http请求验证手机号是否在服务端注册了"); console.log(this.mobile) } } }).mount("#app"); </script> </body> </html>
4.2 事件修饰符
子元素的同类事件触发以后,会自动触发父类元素的同类事件,这就是事件冒泡。
事件修饰符 | 描述 |
@事件名.stop | 用于阻止事件冒泡 |
@事件名.prevent | 用于阻止标签本身拥有的页面跳转功能,例如:a标签被点击,form标签提交表单 |
代码示例

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="app"> <div @click="show('div')"> <button @click.stop="show('button')">点击</button> <a @click="show('a')" href="http://www.baidu.com">点击</a> </div> </div> <script> var vm=Vue.createApp({ data(){ return{ } }, methods: { show(msg){ console.log(`${msg}被点击了`) } } }).mount("#app") </script> </body> </html>
五 webStorage本地存储
webStorage是HTML5提供的用于在本地实现离线存储的一种技术方案。HTML5中提供了2个全局对象用于保存数据到本地浏览器或者移动端的webapp中,分别是:localStorage和sessionStorage。这2个对象,使用方式一致,区别仅仅是存储数据的有效期不同。这个对象保存数据时,都是域名进行区分保存的,不同的域名保存在本地存储的相互之间是互不干扰,互不影响的。
webStorage本地存储 | 描述 | 用法 | ||
localStorage | 永久存储,不主动删除,会一直保存在本地。 |
|
||
sessionStorage | 会话存储,当浏览器重启以后,数据则会丢失。 |
|
实例代码:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>todolist</title> <style> .list_con{ width:600px; margin:50px auto 0; } .inputtxt{ width:550px; height:30px; border:1px solid #ccc; padding:0px; text-indent:10px; } .inputbtn{ width:40px; height:32px; padding:0px; border:1px solid #ccc; } .list{ margin:0; padding:0; list-style:none; margin-top:20px; } .list li{ height:40px; line-height:40px; border-bottom:1px solid #ccc; } .list li span{ float:left; } .list li a{ float:right; text-decoration:none; margin:0 10px; } </style> <script src="assets/vue.global.3.2.20.js"></script> </head> <body> <div class="list_con" id="todolist"> <h2>To do list</h2> <input type="text" v-model="text" id="txt1" class="inputtxt"> <input type="button" value="增加" id="btn1" class="inputbtn" @click="add_item"> <ul id="list" class="list"> <!-- javascript:; # 阻止a标签跳转 --> <li v-for="(item,key) in item_list"> <span>{{item}}</span> <a href="" class="up" @click.stop.prevent="up_item(key)"> ↑ </a> <a href="javascript:;" @click.stop.prevent="down_item(key)"class="down"> ↓ </a> <a href="" class="del" @click.stop.prevent="remove_item(key)">删除</a> </li> </ul> </div> <script> var vm = Vue.createApp({ data(){ return { text: "", item_list: [ "学习html", "学习css", "学习javascript", ] } }, methods: { add_item(){ // 添加计划 this.load_data(); this.item_list.splice(0,0,this.text); this.text = ""; }, remove_item(key){ // 删除计划 this.item_list.splice(key,1); }, up_item(key){ // 计划向上移动 if( key === 0) return; // 如果当前计划已经在最上方,则不能继续向上移动 let del_list = this.item_list.splice(key,1); this.item_list.splice(key-1, 0, del_list[0]); }, down_item(key){ // 计划向下移动 let del_list = this.item_list.splice(key,1); this.item_list.splice(key+1, 0, del_list[0]) }, save_data(){ let content = JSON.stringify(this.item_list) //保存为字符串 localStorage.setItem("todolist", content); }, load_data(){ if ( localStorage.getItem("todolist")!== true){ localStorage.setItem("todolist",JSON.stringify(this.item_list)); } let content = localStorage.getItem("todolist") try { this.item_list = JSON.parse(content); //JSON数据->JS对象 }catch (e) { console.log("转换json数据出错!") } } }, created(){ this.load_data(); }, updated(){ this.save_data(); } }).mount("#todolist") </script> </body> </html>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix