计算属性与属性监听
# 1 计算属性
# 1.1 基本使用
需求:翻转字符串案例
计算属性是一个属性,写法上是一个函数,这个函数的返回值就是计算属性最终的值。
- 计算属性必须定义在 computed 节点中
- 计算属性必须是一个 function,计算属性必须有返回值
- 计算属性不能被当作方法调用,当成属性来用
定义计算属性
// 组件的数据: 需要计算的属性
computed: {
reverseMsg () {
return this.msg.split('').reverse().join('')
}
}
使用计算属性
<p>{{ reverseMsg }}</p>
# 1.2 计算属性的缓存的问题
计算属性: 缓存
计算属性只要计算了一次,就会把结果缓存起来,以后多次使用计算属性,直接使用缓存的结果,只会计算一次。
计算属性依赖的属性一旦发生了改变,计算属性会重新计算一次,并且缓存
// 计算属性只要计算了一次,就会把结果缓存起来,以后多次使用计算属性,直接使用缓存的结果,只会计算一次。
// 计算属性依赖的属性一旦发生了改变,计算属性会重新计算一次,并且缓存
export default {
data () {
return {
msg: 'hello'
}
},
computed: {
reverseMsg() {
console.log('我执行了')
return this.msg.split('').reverse().join('')
}
}
}
# 1.3 成绩案例-计算属性处理总分 和 平均分
- 在computed中提供计算属性
computed: {
sumScore () {
return this.list.reduce((sum, item)=> sum + item.score, 0)
},
avgScore () {
return this.list.length ? (this.sumScore / this.list.length).toFixed(2) : 0
}
},
- 在模板中直接渲染计算属性
<tfoot>
<tr>
<td colspan="5">
<span>总分:{{sumScore}}</span>
<span style="margin-left:50px">平均分:{{avgScore}}</span>
</td>
</tr>
</tfoot>
# 1.4 计算属性的完整写法
// 1. 计算属性默认情况下只能获取,不能修改。
// 2. 计算属性的完整写法
/*
computed: {
full() {},
full: {
get() {
return this.first + ' ' + this.last
},
set(value) {
}
}
}
*/
computed: {
full: {
get () {
...
},
set (value) {
...
}
}
}
# 1.5 小案例- 全选反选
目标: 完成全选和反选的功能
注意: 小选框都选中(手选/点反选), 全选自动选中
图示:
标签和数据准备(可复制):
<template>
<div>
<span>全选:</span>
<input type="checkbox" />
<button >反选</button>
<ul>
<li >
<input type="checkbox" />
<span>名字</span>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
arr: [
{
name: "猪八戒",
c: false,
},
{
name: "孙悟空",
c: false,
},
{
name: "唐僧",
c: false,
},
{
name: "白龙马",
c: false,
},
],
};
}
};
</script>
<style>
</style>
正确答案(==不可复制==):
<template>
<div>
<span>全选:</span>
<!-- 4. v-model 关联全选 - 选中状态 -->
<input type="checkbox" v-model="isAll"/>
<button @click="btn">反选</button>
<ul>
<li v-for="(obj, index) in arr" :key="index">
<!-- 3. 对象.c - 关联 选中状态 -->
<input type="checkbox" v-model="obj.c"/>
<span>{{ obj.name }}</span>
</li>
</ul>
</div>
</template>
<script>
// 目标: 小选框 -> 全选
// 1. 标签+样式+js准备好
// 2. 把数据循环展示到页面上
export default {
data() {
return {
arr: [
{
name: "猪八戒",
c: false,
},
{
name: "孙悟空",
c: false,
},
{
name: "唐僧",
c: false,
},
{
name: "白龙马",
c: false,
},
],
};
},
// 5. 计算属性-isAll
computed: {
isAll: {
set(val){
// 7. 全选框 - 选中状态(true/false)
this.arr.forEach(obj => obj.c = val)
},
get(){
// 6. 统计小选框状态 -> 全选状态
return this.arr.every(obj => obj.c === true)
}
}
},
methods: {
btn(){
// 8. 让数组里对象的c属性取反再赋予回去
this.arr.forEach(obj => obj.c = !obj.c)
}
}
};
</script>
<style>
</style>
# 2 属性监听
# 2.1 基本使用
当需要监听某个数据是否发生改变,就要用到watch
/*
watch: {
// 只要属性发生了改变,这个函数就会执行
属性: function () {
}
}
*/
watch: {
// 参数1: value 变化后的值
// 参数2: oldValue 变化前的值
msg (value, oldValue) {
console.log('你变了', value, oldValue)
}
}
# 2.2 复杂类型的监听-监听的完整写法
如果监听的是复杂数据类型,需要深度监听,需要指定deep为true,需要用到监听的完整的写法
// 1. 默认情况下,watch只能监听到简单类型的数据变化,如果监听的是复杂类型,只会监听地址是否发生改变,不会监听对象内部属性的变化。
// 2. 需要使用监听的完整写法 是一个对象
watch: {
// friend (value) {
// console.log('你变了', value)
// }
friend: {
// handler 数据发生变化,需要执行的处理程序
// deep: true 如果true,代表深度监听,不仅会监听地址的变化,还会监听对象内部属性的变化
// immediate: 立即 立刻 是否立即监听 默认是false 如果是true,代表页面一加载,会先执行一次处理程序
handler (value) {
console.log('你变了', value)
},
deep: true,
immediate: true
}
},
# 2.3 成绩案例-监听数据进行缓存
- 监听list的变化
watch: {
list: {
deep: true,
handler() {
localStorage.setItem('score-case', JSON.stringify(this.list))
}
}
},
- 获取list数据的时候不能写死,从localStorage中获取
data() {
return {
list: JSON.parse(localStorage.getItem('score-case')) || [],
subject: '',
score: '',
}
},
上次更新: 2023/11/10, 18:35:34