前端Vue3.Vue组件的属性和方法
墨颜丶属性与方法基础
组件的数据都放在了data
选项中,Vue组件的data
选项是一个函数,组件在被创建时会调用此函数来构建响应性的数据系统。
属性基础
在Vue组件中定义的属性数据,我们可以直接使用组件来调用,这是因为Vue在组织数据时,任何定义的属性都会暴露在组件中。实际上,这些属性数据是存储在组件的$data
对象中的,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| const App = { data(){ return{ conunt:111, } } }
let instance = Vue.createApp(App).mount("#Application")
console.log(instance.conunt)
console.log(instance.$data.conunt)
|
运行上面的代码,通过控制台可以看出,使用组件实例直接获取属性与使用$data
的方法获取属性的结果是一样的,本质上访问的是同一块数据。无论那种方式对数据进行修改后,两种获取方式获取到的值都会发生改变
1 2 3 4 5
| instance.conunt = 555
console.log(instance.conunt) console.log(instance.$data.conunt)
|
方法基础
组件的方法被定义在methods
选项中,我们在实现组件的方法时,可以放心地在其中使用this
关键字,Vue自动将其绑定到当前组件实例本身。例如,添加一个add方法
1 2 3 4 5 6 7 8
| methods:{ add(){ this.conunt ++ } } instance.add() console.log(instance.conunt)
|
计算属性和侦听器
计算属性
前面章节中的示例代码,我们定义的属性都是存储属性
,与之相对的还有计算属性
。
判断组件中conunt
大于10,输出大
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const App = { data(){ return{ conunt:111, } }, computed:{ type(){ return this.conunt > 10 ? "大" : "小" } }, methods:{ add(){ this.conunt ++ } } }
let instance = Vue.createApp(App).mount("#Application") console.log(instance.type) instance.conunt=1 console.log(instance.type)
|
计算属性的强大在于,当会影响其值的存储属性发生变化时,计算属性也会同步进行更新,如果元素绑定了计算属性,其也会同步进行更新。
1 2 3 4
| <div>{{type}}</div> <button @click="add">Add</button>
// instance.conunt=9
|
点击button按钮,conunt大于10时,页面对应的小会变成大
使用计算属性还是函数
1 2 3 4 5 6 7 8
| methods:{ add(){ this.conunt ++ }, typeFunc(){ return this.conunt > 10 ? "大" : "小" } }
|
使用函数或计算属性的结果完全一致,事实上,计算属性基于其依赖的存储属性的值的变化而重新计算的,计算完成后会其结果会被缓存
,下次访问计算属性时,其依赖的值没有发生变化,其内的逻辑代码就不会重复执行。函数则不同,每次访问其都会重新执行函数内容得到结果。
根据是否需要缓存,来选择计算属性还是函数。
计算属性的赋值
存储属性主要用于数据的存取,计算属性只用来取值,不会用来存值。因此计算属性默认提供的取值方法get
。
这并不代表计算属性不支持赋值,计算属性也可以通过赋值进行存取数据操作,存数据的方法我们需要手动实现,通常称之为set
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| computed:{ type:{ get(){ return this.conunt > 10 ? "大" : "小" }, set(newValue){ if (newValue == "大"){ this.conunt=121 }else{ this.conunt=0 } } } },
|
赋值时会调用我们定义的set
方法,从而实现对存储属性进行赋值。
1 2 3 4 5 6 7
| let instance = Vue.createApp(App).mount("#Application")
console.log(instance.conunt) console.log(instance.type) instance.type="小" console.log(instance.conunt)
|
如果一个计算属性只实现了get
方法没有实现set
方法,则在使用时只能进行取值操作
属性侦听器
属性侦听时Vue非常强大的功能之一,使用属性侦听可以方便的监听某个属性的变化,以完成复杂的业务逻辑。
例如,我们使用搜索引擎在搜索框中写入关键字后,网页上会自动关联一些关键词供用户选择。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>输入字符超过10时,就会有警告弹窗</title> <script src="https://unpkg.com/vue@3.2.47/dist/vue.global.js"></script> </head> <body> <div id="Application"> <input v-model="searchText"/> </div> <script> const App = { data(){ return { searchText : "", } }, watch:{ searchText(oldValue,newValue){ if (newValue.length > 10){ alert('文本太长了') } } } } Vue.createApp(App).mount("#Application") </script> </body> </html>
|
进行函数限流
在工程开发中,限流是一个非常重要的概念。
场景一:单击某个按钮会从后端服务器发起数据请求,在数据请求回来之前,用户额外的单击是无效且消耗性能的。
场景二:某个按钮会导致页面的更新,我们需要限制用户频繁操作。
手动实现一个简易的限流函数
功能:单击按钮打印方法输出当前时间,要求这个按钮两次事件触发间隔不能小于2秒
方法:思路是用一个变量来控制按钮是否可以触发,触发时对此变量进行修改,2秒后将变量值还原
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://unpkg.com/vue@3.2.47/dist/vue.global.js"></script> </head> <body> <div id="Application"> <button @click="click">刷新</button> </div> <script> const App = { data(){ return{ throttle:false } }, methods:{ click(){ if (!this.throttle){ console.log(Date()) }else{ return } this.throttle=true setTimeout(() => { this.throttle = false },2000); } } } Vue.createApp(App).mount("#Application") </script> </body> </html>
|
使用Lodash库进行函数限流
有许多第三方工具库都提供了函数限流功能,它们强大易用,Lodash
库就是其中之一
简介:
Lodash 是一个 JavaScript 实用工具库,提供一致性,及模块化、性能和配件等功能。
Lodash 消除了处理数组的麻烦,从而简化了 JavaScript、 数字、对象、字符串等。
Lodash 库中提供了debounce函数来进行方法的调用限流,要使用它,首先需要引入Lodas库,代码如下:
1
| <script src="https://unpkg.com/lodash@4.17.20/lodash.min.js"></script>
|
修改代码如下
1 2 3 4 5 6 7 8
| const App = { methods:{ click:_.debounce(function(){ console.log(Date()) },2000) } } Vue.createApp(App).mount("#Application")
|
表单数据的双向绑定
文本输入框
文本输入框的数据绑定:直接使用v-model
指令设置即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://unpkg.com/vue@3.2.47/dist/vue.global.js"></script> </head> <body> <div id="Application"> <input v-model="textField"> <p>文本输入框内容{{textField}}</p> </div> <script> const App = { data(){ return{ textField:'' } }, } Vue.createApp(App).mount("#Application") </script>
</body> </html>
|
多行文本输入区域
多行文本可以使用textarea
标签来实现,textarea
数据绑定方式和input
一样
1 2
| <textarea v-model="textField" cols="30" rows="10"></textarea> <p>多行文本输入框内容{{textField}}</p>
|
复选框与单选框
input类型设置为checkbox
时,其就会以复选框的样式进行渲染。如果只有一个复选框,在使用v-model指令进行数据绑定时,可以直接将其绑定为布尔值。
1 2 3 4 5 6 7 8 9 10
| <input type="checkbox" v-model="checkbox"> <p>{{checkbox}}</p>
data(){ return{ textField:'', checkbox:'', } },
|
复选框一般都是成组出现的,这时我们可以为每一个复选框元素设置一个特殊的值。通过数组属性的绑定来获取每个复选框是否被选中,如果被选中,则数组中会存在其所关联的值;如果没有被选中,则数组中其关联的值会被删除掉。
1 2 3 4
| <input type="checkbox" value="足球" v-model="checkLIst">足球 <input type="checkbox" value="篮球" v-model="checkLIst">篮球 <input type="checkbox" value="排球" v-model="checkLIst">排球 <p>{{checkLIst}}</p>
|
单选框的数据绑定与复选框类似,对每一个单选框元素都可以设置一个特殊的值,并将同一组单选框绑定到同一个属性中即可
1 2 3
| <input type="radio" value="男" v-model="sex">男 <input type="radio" value="女" v-model="sex">女 <p>{{sex}}</p>
|
vue代码示例:
1 2 3 4 5 6 7 8 9 10 11 12
| <script> const App = { data(){ return{ textField:'', checkbox:'', checkLIst:[] } }, } Vue.createApp(App).mount("#Application") </script>
|

选择列表
单选的选择列表,可以直接绑定到Vue组件的一个属性上
多选的选择列表,可以将其绑定到数组属性上
1 2 3 4 5
| <select v-model="select"> <option>男</option> <option>女</option> </select> <p>{{select}}</p>
|
select
标签内部,option
标签用来定义一个选项,若要支持多选操作,则只需要为其添加上multiple
属性即可
1 2 3 4 5 6
| <select v-model="selectList" multiple> <option>篮球</option> <option>足球</option> <option>排球</option> </select> <p>{{selectList}}</p>
|
vue示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <script> const App = { data(){ return{ textField:'', checkbox:'', checkLIst:[], sex:'', select:'', selectList:[] } }, } Vue.createApp(App).mount("#Application") </script>
|
两个常用的修饰符
在对表单进行数据绑定时,可以使用修饰符来控制绑定指令的一些行为。比较常用的修饰符有lazy
和 trim
lazy修饰符类似于属性的懒加载。
当v-model对文本输入框进行绑定时,输入框发生变化都会同步修改对应属性的值。某些业务情况下,我们并不需要实时关注输入框文字的变化,只需要用户输入完成后在关注值的变化,这时就可以使用lazy
修饰符
1 2
| <input v-model.lazy="textField"> <p>文本输入框内容{{textField}}</p>
|
运行上面代码,只有用户输入完成,即输入框失去焦点后,段落中的textField
才会同步输入框中的textField
trim
修饰符的作用是将绑定的文本数据的首尾空格去掉
,很多应用场景,用户输入的数据需要提交给后端处理
1 2
| <input v-model.trim="textField"> <p>文本输入框内容{{textField}}文本输入框内容</p>
|
样式绑定
在Vue中对class属性的数据绑定做了增强,可以方便通过布尔值控制其设置的样式是否被选用
HTML标签绑定Class属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://unpkg.com/vue@3.2.47/dist/vue.global.js"></script> <style> .red{ color: red; } .blue{ color: blue; } </style> </head> <body> <div id="Application"> <div :class="{blue:isBlue,red:isRed}"> 示例文案 </div> </div> <script> const App = { data(){ return{ isBlue:true, isRed:false } } } Vue.createApp(App).mount("#Application") </script> </body> </html>
|
以上代码所示,其中div元素的class属性的值会根据isBlue,isRed属性的值而改变。如果设置对象有多个属性的值都为true,则都会被添加class属性中。
在实际开发中,不一定用内联的方式为class绑定控制对象,可以直接将其设置为一个Vue组件中的数据对象,修改代码如下
1 2 3
| <div :class="style"> 示例文案 </div>
|
1 2 3 4 5 6 7 8 9 10
| const App = { data(){ return{ style:{ blue:true, red:false } } }
|
Vue还支持用数组对象来控制class属性
1 2 3
| <div :class="[blueClass,redClass]"> 示例文案 </div>
|
1 2 3 4 5 6
| data(){ return{ redClass:'red', blueClass:"blue", } }
|
绑定内联样式
内联样式是指通过HTML元素的style属性来设置样式,style属性可以直接通过javascript对象来设置样式,我们也可以通过内部使用Vue属性
1 2 3
| <div :style="{color: color,fontSize: font}"> 示例文案 </div>
|
1 2 3 4 5 6
| data(){ return{ color:'green', font:'50px', } }
|
需要注意,外部定义CSS属性在命名时,多采用-
如font-size
,内联命名时多采用驼峰命名法如fontSize
。直接绑定对象属性在实际开发中更加常用。
范例:实现一个功能完整的用户注册页面
搭建用户注册页面
搭建用户注册页面,页面由标题,信息输入框,偏好设置,确认按钮
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <div class="container" id="Application"> <div class="container"> <div class="subTitle">加入我们,一起创造美好世界</div> <h1 class="title">创建你的账号</h1> <div v-for="(item,index) in fields" class="inputContainer"> <div class="field">{{item.title}} <span v-if="item.required" style="color: red;">*</span></div> <input class="input" type="item.type"> <div class="tip" v-if="index == 2">请确认密码需要大于6位</div> </div>
<div class="subContainer"> <div class="setting">偏好设置</div> <input class="checkbox" type="checkbox"><label class="label">接收更新邮件</label> </div> <button class="btn">创建账号</button> </div> </div>
|
Vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <script> const App={ data(){ return{ fields:[ { title:'用户名', required:true, type:'text' }, { title:'邮箱地址', required:true, type:'text' }, { title:'密码', required:true, type:'password' }, ] } } } Vue.createApp(App).mount("#Application") </script>
|
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| <style> .container { margin: 0 auto; margin-top: 70px; text-align: center; width: 300px; } .subTitle { color: gray; font-size: 14px; } .title { font-size: 45px; } .input { width: 90%; } .inputContainer { text-align: left; margin-bottom: 20px; } .subContainer { text-align: left; } .field { font-size: 14px; } .input { border-radius: 6px; height: 25px; margin-top: 10px; border-color: silver; border-style: solid; background-color: cornsilk; } .tip { margin-top: 5px; font-size: 12px; color: gray; } .setting { font-size: 9px; color: black; } .label { font-size: 12px; margin-left: 5px; height: 20px; vertical-align: middle; } .checkbox { height: 20px; vertical-align: middle; } .btn { border-radius: 10px; height: 40px; width: 300px; margin-top: 30px; background-color: deepskyblue; border-color: blue; color: white; } </style>
|

实现注册页面的用户交互
获取用户输入的账号密码等,密码必须大于6位,邮箱校验
页面中3个文本输入框是通过循环动态渲染的,因此也需要采用动态的方式进行绑定
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <div class="container" id="Application"> <div class="container"> <div class="subTitle">加入我们,一起创造美好世界</div> <h1 class="title">创建你的账号</h1> <div v-for="(item,index) in fields" class="inputContainer"> <div class="field">{{item.title}} <span v-if="item.required" style="color: red;">*</span></div> <input v-model="item.model" class="input" :type="item.type"> <div class="tip" v-if="index == 2">请确认密码需要大于6位</div> </div>
<div class="subContainer"> <div class="setting">偏好设置</div> <input v-model="receiveMsg" class="checkbox" type="checkbox"><label class="label">接收更新邮件</label> </div> <button @click="createAccount" class="btn">创建账号</button> </div> </div>
|
Vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| <script> const App={ data(){ return{ fields:[ { title:'用户名', required:true, type:'text', model:'' }, { title:'邮箱地址', required:true, type:'text', model:'' }, { title:'密码', required:true, type:'password', model:'' }, ], receiveMsg:false } }, computed:{ name:{ get(){ return this.fields[0].model }, set(value){ this.fields[0].model=value } }, email:{ get(){ return this.fields[1].model }, set(value){ this.fields[1].model=value } }, password:{ get(){ return this.fields[2].model }, set(value){ this.fields[2].model=value } }, }, methods:{ emailCheck(){ var verify = /^\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/; if (!verify.test(this.email)){ return false }else{ return true } }, createAccount(){ if (this.name.length == 0){ alert("请输入用户名") return }else if (this.password.length <= 6){ alert("密码需要6位以上") return }else if (this.email.length > 0 && !this.emailCheck(this.email)){ alert("请输入正确的邮箱") return } alert('注册成功')
} } } Vue.createApp(App).mount("#Application") </script>
|
通过配置输入框field
对象来实现动态数据绑定,当用户单击创建账号按钮时,createAccount
方法会进行一些有效性的校验。
