一、computedAPI
1.1前言:在模板中,可以通过插值语法显示一些data中的数据,但是在某些情况下,一些数据可能需要进行转换后再显示eg:需要对多个data数据进行进行运算、三元运算符来决定结果、数据进行某种转化后显示;在模板中使用表达式,可以非常方便的实现,但是设计它们的初衷是用于简单的运算; 在模板中放入太多的逻辑会让模板过重和难以维护; 并且如果多个地方都使用到,那么会有大量重复的代码,我们可以把逻辑抽离出去有一种方法是将逻辑抽离到一个method中,还有一种方法是使用计算属性computed,下面解释一下两种方法的区别:
1.2 method
<teamplate id="app">
<!-- 插值语法表达式直接进行拼接 -->
<!-- 1.拼接名字 -->
<view>{{ getFullname() }}</view>
<view>{{ getFullname() }}<view>
<view>{{ getFullname() }}</view>
<!-- 2.显示分数等级 -->
<view>{{ getScoreLevel() }}</view>
<!-- 3.反转单词显示文本 -->
<view>{{ reverseMessage() }}</view>
</teamplate>
<script>
export default {
data() {
return {
// 1.姓名
firstName: "kobe",
lastName: "bryant",
// 2.分数: 及格/不及格
score: 80,
// 3.一串文本: 对文本中的单词进行反转显示
message: "my name is why"
},
methods: {
getFullname() {
return this.firstName + " " + this.lastName
},
getScoreLevel() {
return this.score >= 60 ? "及格": "不及格"
},
reverseMessage() {
return this.message.split(" ").reverse().join(" ")
}
}
}
</script>
1.3 computed
<teamplate id="app">
<view>{{ fullname }}</view>
<view>{{ fullname }}</view>
<view>{{ fullname }}</view>
<!-- 2.显示分数等级 -->
<view>{{ scoreLevel }}</view>
<!-- 3.反转单词显示文本 -->
<view>{{ reverseMessage }}</view>
</teamplate>
<script>
export default {
data() {
return {
// 1.姓名
firstName: "kobe",
lastName: "bryant",
// 2.分数: 及格/不及格
score: 80,
// 3.一串文本: 对文本中的单词进行反转显示
message: "my name is why"
}
},
computed: {
// 1.计算属性默认对应的是一个函数
fullname() {
return this.firstName + " " + this.lastName
},
scoreLevel() {
return this.score >= 60 ? "及格": "不及格"
},
reverseMessage() {
return this.message.split(" ").reverse().join(" ")
}
}
}
</script>
似乎看上去没有什么不同,下面看一下他们的打印结果
computed和method的区别在于computed计算属性带缓存这样可以做到性能优化
上述代码中的语法computed是一个对象,要计算的属性是一个函数,这是一个语法糖,计算属性有自己完整的写法
<teamplate id="app">
<view>
<view>{{ fullname }}</view>
<button @click="setFullname">设置fullname</button>
</view>
</teamplate>
<script>
export default {
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"
}
}
}
</script>
二、watchAPI
开发中我们在data返回的对象中定义了数据,这个数据通过插值语法等方式绑定到template中; 当数据变化时,template会自动进行更新来显示最新的数据; 但是在某些情况下,我们希望在代码逻辑中监听某个数据的变化,这个时候就需要用侦听器watch来完成了;
2.1基本用法
<teamplate id="app">
<view>{{message}}</view>
<button @click="changeMessage">修改message</button>
</teamplate>
<script>
export default {
data() {
return {
message: "Hello Vue",
info: { name: "why", age: 18 }
}
},
methods: {
changeMessage() {
this.message = "你好啊, 李银河!"
this.info = { name: "kobe" }
}
},
watch: {
// 1.默认有两个参数: newValue/oldValue
message(newValue, oldValue) {
console.log("message数据发生了变化:", newValue, oldValue)
},
info(newValue, oldValue) {
console.log(newValue.name, oldValue.name)
}
}
}
</script>
如果我们要监听的是复杂类型,是监听不到的,这时就需要watch的完整写法了
2.2完整写法
<teamplate id="app">
<view>{{ info.name }}</view>
<button @click="changeInfo">修改info</button>
</teamplate>
<script>
// 1.创建app
export default {
data() {
return {
info: { name: "why", age: 18 }
}
},
methods: {
changeInfo() {
// 1.创建一个新对象, 赋值给info
// this.info = { name: "kobe" }
// 2.直接修改原对象某一个属性
this.info.name = "kobe"
}
},
watch: {
// 默认watch监听不会进行深度监听
// info(newValue, oldValue) {
// console.log("侦听到info改变:", newValue, oldValue)
// }
// 进行深度监听
info: {
handler(newValue, oldValue) {
console.log("侦听到info改变:", newValue, oldValue)
console.log(newValue === oldValue)
},
// 监听器选项:
// info进行深度监听
deep: true,
// 第一次渲染直接执行一次监听器
immediate: true
},
"info.name": function(newValue, oldValue) {
console.log("name发生改变:", newValue, oldValue)
}
}
}
</script>
三、案例
toggleStatus(item, index) {
item.status = !item.status
// 思路:把选中的数组过滤出来 再去计算
let arr = this.list.filter(function(item){return item.status}) // 把选中的数组过滤出来 赋值给arr
let sum = 0 // 算出总价钱用的
arr.forEach(function(item){ return sum += item.price * item.num
}) //计算价钱
this.allPrice = sum // 赋值给上面的变量
console.log('总价钱',sum,'当前选中的数组',arr);
},
简便写法:在计算属性中
computed: {
getAllPrice() {
return this.list.filter(function(item){ return item.status
}).reduce(function(previousValue, item){
return previousValue + item.price * item.num
}, 0)
}, }