目录
Computed 计算属性
Computed 概念
**概念:**实时监听数据的变化,并返回计算后的新值,供组件渲染 DOM 时使用。
**本质:**function函数
**特点:**缓存特性,Computed会对计算出来的结果缓存,再次使用数据时会直接读取缓存。
语法:
export default {
name: 'MyCounter',
data() {
return {
count: 1,
}
},
computed: {
// 计算属性:监听data中count值的变化,自动计算出count*2之后的新值
plus() {
return this.count * 2
}
}
}
案例(Vue2): 小黑的礼物清单
需求:礼物总数与表单中的数量之和同步
-
Code:
<!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> <style> table { border: 1px solid #000; text-align: center; width: 240px; } th,td { border: 1px solid #000; } h3 { position: relative; } </style> </head> <body> <div id="app"> <h3>小黑的礼物清单</h3> <table> <tr> <th>名字</th> <th>数量</th> </tr> <tr v-for="(item, index) in list" :key="item.id"> <td>{ { item.name }}</td> <td>{ { item.num }}个</td> </tr> </table> <!-- 目标:统计求和,求得礼物总数 --> <p>礼物总数:{ { plus }} 个</p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { // 现有的数据 list: [ { id: 1, name: '篮球', num: 1 }, { id: 2, name: '玩具', num: 2 }, { id: 3, name: '铅笔', num: 5 }, ] }, computed: { plus() { let total = this.list.reduce((sum, item) => sum += item.num, 0) return total } } }) </script> </body> </html>
reduce参考:https://blog.youkuaiyun.com/qq_38970408/article/details/121018660
注意:计算属性侧重于得到一个计算的结果,因此计算属性中必须有 return 返回值!
使用注意点:
① 计算属性必须定义在 computed 节点中
② 计算属性必须是一个 function 函数
③ 计算属性必须有返回值
④ 计算属性必须当做普通属性使用
比如 { {plus}}, 而非是这样用:{ {plus()}}
Computed 完整写法
计算属性也是属性,能访问,也应能修改
- 计算属性默认的简写,只能读取访问,不能 “修改”
- 如果要 “修改” → 需要写计算属性的完整写法
注:建议结合以下例子理解
computed: {
计算属性名: {
get(): {
代码逻辑
return res
},
set(修改的值): {
代码逻辑
}
}
}
结合基础案例理解:
**案例:**基础案例
-
Code:
<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> </head> <body> <div id="app"> <h2>{ { fullname }}</h2> <button @click="setFullname">设置fullname</button> </div> <script src="../lib/vue.js"></script> <script> // 1.创建app const app = Vue.createApp({ // data: option api data() { return { firstname: "coder", lastname: "why" } }, computed: { // 语法糖的写法 // fullname() { // return this.firstname + " " + this.lastname // }, // 完整的写法: fullname: { get: function() { return this.firstname + " " + this.lastname }, set: function(value) { const names = value.split(" ") this.firstname = names[0] this.lastname = names[1] } } }, methods: { setFullname() { this.fullname = "kobe bryant" } } }) // 2.挂载app app.mount("#app") </script> </body> </html>
案例(Vue2):通过改名卡,能够修改姓和名
-
Code:
<!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> <style> input { width: 30px; } </style> </head> <body> <div id="app"> 姓:<input type="text" v-model="firstName"> + 名:<input type="text" v-model="lastName"> = <span>{ { fullName }}</span><br><br> <button @click="changeName">改名卡</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { firstName: '刘', lastName: '备', }, methods: { changeName () { this.fullName = '黄忠' } }, computed: { // 简写 → 获取,没有配置设置的逻辑 // fullName () { // return this.firstName + this.lastName // } // 完整写法 → 获取 + 设置 fullName: { // (1) 当fullName计算属性,被获取求值时,执行get(有缓存,优先读缓存) // 会将返回值作为,求值的结果 get () { return this.firstName + this.lastName }, // (2) 当fullName计算属性,被修改赋值时,执行set // 修改的值,传递给set方法的形参 set (value) { // console.log(value.slice(0, 1)) // console.log(value.slice(1)) this.firstName = value.slice(0, 1) this.lastName = value.slice(1) } } } }) </script> </body> </html>
计算属性 vs 方法
1-computed计算属性
作用:封装了一段对于数据的处理,求得一个结果
语法:
- 写在computed配置项中
- 作为属性,直接使用js中使用计算属性: this.计算属性模板中使用计算属性:{ {计算属性}}
2-methods方法
作用:给Vue实例提供一个方法,调用以处理业务逻辑。
语法:
- 写在methods配置项中
- 作为方法调用
- js中调用:this.方法名()
- 模板中调用 { {方法名()}} 或者 @事件名=“方法名”
计算属性的优势
1-缓存特性:(提升性能)计算属性会对计算出来的结果缓存,再次使用直接读取缓存。
2-methods没有缓存特性
案例:
理解:计算属性会对计算的结果缓存,下一次直接提缓存结果即可,如图计算属性就仅计算了一次,而methods是调用几次就计算几次。很明显,前者资源开销更低。
-
Code:
<template> <div> <!-- 通过v-model进行双向数据绑定。 .number指自动将用户的输入值转为数值类型 --> <input type="text" v-model.number="count" /> <p>{ { count }} 乘以2的值为: { { plus }}</p> <p>{ { count }} 乘以2的值为: { { plus }}</p> <p>{ { count }} 乘以2的值为: { { plus }}</p> <hr/> <p>{ { count }} 乘以2的值为: { { m_plus() }}</p> <p>{ { count }} 乘以2的值为: { { m_plus() }}</p> <p>{ { count }} 乘以2的值为: { { m_plus() }}</p> </div> </template> <script> export default { name: 'MyCounter', data() { return { count: 1, } }, computed: { // 计算属性:监听data中count值的变化,自动计算出count*2之后的新值 plus() { console.log("计算属性被执行了"); return this.count * 2 } }, methods: { m_plus() { console.log("方法被执行了"); return this.count * 2 } } } </script>
案例(Vue2):水果购物车
案例需求,使用计算属性动态计算:
① 已勾选的商品总个数 ② 已勾选的商品总价 ③ 结算按钮的禁用状态
-
Code:
computed: { //动态计算出勾选水果的总数量 total() { let t = 0 this.fruitlist.forEach(x => { if(x.state) { t += x.count } }) return t }, amount() { let a = 0 this.fruitlist .filter(x => x.state) .forEach(x => { a += x.price * x.count }) return a }, isDisabled() { this.total === 0 } },
**注意:**这里的this指的是当前组件实例
computed: {
isDisabled() {
this.toal === 0
}
}
watch 侦听器
Sum:
watch 侦听器:
概念:监听数据变化,并执行一些业务逻辑或异步操作。
简单写法:
watch: {
数据属性名(newVal, oldVal) {
业务逻辑 或 异步操作
}
‘对象.属性名’(newVal, oldVal) {
业务逻辑 或 异步操作
}
}
完整写法:
watch: {
数据属性名:{
deep: true, // 深度监听
immediate: true, // 是否立刻执行一次 handler
handler (newValue) {
业务逻辑 或 异步操作
}
}
}
常用属性:
immediate
:采用immediate后组件在初次加载完毕后会调用 watch 侦听器
deep
:当 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用 deep 选项。
注意事项:
- watch监听对象,打印输出的是代理对象(具体见以下案例)
- watch监听对象,watch监听对象,对象整体被覆盖,则新旧值不一致;若只是对象属性值变化,则新旧值还算一致
watch 概念
概念:监视数据变化,执行一些业务逻辑或异步操作。
应用场景:
1-监视用户名的变化并发起请求,判断用户名是否可用。
2-实时翻译
语法:在 watch 节点下,定义自己的侦听器。
export default {
data() {
return {
username: ''
}
},
watch: {
// 监听 username 的值的变化
// 形参列表中,第一个值是“变化后的新值”,第二个值是“变化之前的旧值”
// 注:oldVal 可以不传
username(newVal, oldVal) {
console.log(newVal, oldVal);
}
}
}
进一步:如果你想要监视某个复杂数据类型中的子属性
const app = new Vue({
el: '#app',
data: {
// words: ''
obj: {
words: ''
}
},
watch: {
'obj.words' (newValue) {
console.log('变化了', newValue)
}
}
**案例:**修改普通值与修改对象时,watch的监听变化
理解:如果是对象类型,那么拿到的是代理对象
-
Code:
<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> </head> <body> <div id="app"> <h2>{ { message }}</h2> <button @click="changeMsg">修改Message</button> <h2>{ { info.name }}</h2> <button @click="changeInfo">修改info</button> </div> <script src="../lib/vue.js"></script> <script> const app = Vue.createApp({ data() { return { message: 'txt'