计算属性
前面的笔记提到了计算属性,这里单独讲一下计算属性
我们知道,在模板中可以直接通过插值语法显示一些data中的数据
但是在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示
- 比如我们有firstName和lastName两个变量,我们需要显示完整的名称。
- 但是如果多个地方都需要显示完整的名称,我们就需要写多个{{firstName}} {{lastName}}
<div id="app">
<h2>{{name}}:{{currentName}}</h2>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
name: '姓名',
currentName: 'Vue'
}
})
</script>
这个场景下,计算属性就可以派上用上了,上面的代码可以这样写
<div id="app">
//这里的showName就是computed里面的showName
<h2>{{showName}}</h2>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
name: '姓名',
currentName: 'Vue'
},
computed: {
//这里的函数名类似于data里面的键名,return出来的类似于data里面的键值。
showName: function () {
return this.name + ':' + this.currentName
}
}
})
</script>
上面的操作是计算属性最简单的操作,接下来继续看
-
每个计算属性都包含一个getter和一个setter
-
在上面的例子中,我们只是使用getter来读取。
-
在某些情况下,你也可以提供一个setter方法(不常用)。
下面分别演示这两种情况
<div id="app">
<h2>书籍总价为:{{allPrice}}</h2>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
bookList: [
{ name: 'java编程思想', price: 99, count: 3 },
{ name: 'unix编程艺术', price: 112, count: 2 },
{ name: 'vueJs程序设计', price: 89, count: 4 },
],
count: 0
},
computed: {
// 这个名字为计算属性名,如果获取,就执行get函数,如果设置就执行set函数
allPrice: {
get() {
let money = this.bookList.reduce((item, curItem) => {
item += curItem.price * curItem.count
return item
}, 0)
return money
},
set(newValue) {
console.log('触发我了', newValue)
let num1 = newValue / 2
this.count = num1
}
}
}
})
</script>
计算属性的缓存
<div id="app">
<h2>姓名:{{allName1}}</h2>
<h2>姓名:{{allName1}}</h2>
<h2>姓名:{{allName1}}</h2>
<h2>姓名:{{allName2()}}</h2>
<h2>姓名:{{allName2()}}</h2>
<h2>姓名:{{allName2()}}</h2>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
name1: '李明',
name2: '韩梅梅',
},
computed: {
allName1() {
console.log('执行了computed属性')
return this.name1 + '和' + this.name2
}
},
methods: {
allName2() {
console.log('执行了methods属性')
return this.name1 + '和' + this.name2
}
}
})
</script>
上面执行了多个计算属性,也执行了多个methods属性,可以看一下打印
可以到计算属性只执行了一个打印,这是因为计算属性具有缓存行
相关属性发生改变,计算属性会重新执行,无关属性发生改变,计算属性不会重新执行。
methods方法和计算属性其实是互补的,有的场景下,我们希望缓存数据,有的我们不需要,就可以分别来使用了两个属性了。
watch监听
watch基础用法
<div id="app">
<h2>{{value}}</h2>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
value: '初始值'
},
watch: {
//接收两个参数,第一个参数是修改后的值,第二个参数是修改前的值
value(newValue, oldValue) {
console.log('value值改变了', newValue, oldValue)
}
}
})
</script>
watch的handler和immediate
<div id="app">
<h2>{{value}}</h2>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
value: '初始值'
},
watch: {
value: {
// 接收两个参数,第一个是新的值,第二个是老的值
//监听的数据后面写成对象形式,包含handler方法和immediate,之前我们写的函数其实就是在写这个handler方法;
handler(newValue, oldValue) {
console.log(newValue, oldValue)
},
// 第一次就开始监听,也就是value是'初始值'的时候就开始执行这个value函数。
immediate: true
}
}
})
</script>
另外,官网有说
注意,不应该使用箭头函数来定义 watcher 函数
例如 searchQuery: newValue => this.updateAutocomplete(newValue)
理由是箭头函数绑定了父级作用域的上下文
所以 this
将不会按照期望指向 Vue 实例,this.updateAutocomplete
将是 undefined。
当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听。
首先看一下如果不加deep
<div id="app">
<h2>{{obj.name}}</h2>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
obj: {
name: '李雷雷',
age: 18
}
},
watch: {
obj(newValue, oldValue) {
console.log('监听的是对象', newValue, oldValue)
}
}
})
</script>
可以看到并没有产生监听
<div id="app">
<h2>{{obj.name}}</h2>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
obj: {
name: '李雷雷',
age: 18
}
},
watch: {
obj: {
handler(newValue, oldValue) {
console.log('监听的是对象', newValue, oldValue)
},
deep: true
}
}
})
</script>
可以看到,如果这样做就可以执行监听的属性了,但是oldValue拿不到修改前的值了。
当然也可以这样
<div id="app">
<h2>{{obj.name}}</h2>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
obj: {
name: '李雷雷',
age: 18
}
},
watch: {
'obj.name': {
handler(newValue, oldValue) {
console.log('监听的是对象', newValue, oldValue)
},
deep: true
}
}
})
</script>
就可以拿到前后的值了
注意: 数组(一维、多维)的变化不需要通过深度监听,对象数组中对象的属性变化则需要deep深度监听。
当然,监听不仅可以监听到data里面的值,还可以监听到vuex里面值得变化,在开发中有通过网络请求下来的数据存到到vuex中,使用watch监听vuex中的数据,并获取到数据,然后渲染到界面上,这种情况在有的开发中有使用,当然也有其他的一些方式。