概述
Hello,我是 Alex 007,一个热爱计算机编程和硬件设计的小白,为啥是007呢?因为叫 Alex 的人太多了,再加上每天007的生活,Alex 007就诞生了。
5.Vue 计算属性和侦听器
这篇文章我们来看一下Vue的计算属性和侦听属性。计算属性是自动监听依赖值的变化,从而动态返回内容,监听是一个过程,在监听的值变化时,可以触发一个回调,并做一些事情。侦听属性watch中可以执行代码逻辑,如函数节流,Ajax异步获取数据,甚至操作 DOM。
计算属性
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message
的翻转字符串。当你想要在模板中多处使用翻转字符串,就会更加难以处理。
所以,对于这种复杂逻辑,Vue给我们提供了更好的解决方案,计算属性。
基础例子
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello'
},
computed: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
})
</script>
</body>
</html>
插值表达式{{ reversedMessage }}首先会去data中找 reversedMessage 这个属性,如果找不到就再去计算属性中去找,找到之后再将它显示在页面上。
这里我们声明了一个计算属性 reversedMessage
。我们提供的函数将用作 property app.reversedMessage
的 getter 函数:
console.log(app.reversedMessage) // => 'olleH'
app.message = 'Goodbye'
console.log(app.reversedMessage) // => 'eybdooG'
你可以打开浏览器的控制台,自行修改例子中的 app。app.reversedMessage
的值始终取决于 app.message
的值。
你可以像绑定普通 property 一样在模板中绑定计算属性。Vue 知道 app.reversedMessage
依赖于 app.message
,因此当 app.message
发生改变时,所有依赖 app.reversedMessage
的绑定也会更新。而且最妙的是我们已经以声明的方式创建了这种依赖关系:计算属性的 getter 函数是没有副作用 (side effect) 的,这使它更易于测试和理解。
计算属性缓存 vs 方法
你可能已经注意到计算属性和我们之前讲过的method有些类似,可以通过在表达式中调用方法来达到同样的效果:
<p>Reversed message: "{{ reversedMessage() }}"</p>
// 在组件中
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message
还没有发生改变,多次访问 reversedMessage
计算属性会立即返回之前的计算结果,而不必再次执行函数。
这也同样意味着下面的计算属性将不再更新,因为 Date.now()
不是响应式依赖:
computed: {
now: function () {
return Date.now()
}
}
相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。
我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。
计算属性的 setter
在 Vue 中,computed 的属性可以被视为跟 data 一样,可以读取和设值,因此在 computed 中可以分成 getter(读取) 和 setter(设值),一般情况下是没有 setter 的,computed 预设只有 getter ,也就是只能读取,不能改变设值。
计算属性默认只有 getter,不过在需要时你也可以提供一个 setter:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: 'Hello'
},
computed: {
reversedMessage: {
get() {
return this.message.split('').reverse().join('')
},
set(value) {
this.message = value
}
}
}
})
</script>
</body>
</html>
现在再运行 app.reversedMessage = "Alex"
时,setter 会被调用,app.reversedMessage
会相应地被更新。
侦听属性
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听属性。这就是为什么 Vue 通过 watch
选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,watch方式是最有用的。
例如,我们可以写一个类似于《答案之书》的小东西。
答案之书,是一本重新定义了读者-作者关系的书。 它的每一页都写有一句有关选择或行动的答案,当你为生活中纷扰繁杂的小事犹豫不决的时候,随意翻开其中一页,让这本书帮你做决定。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<p>
Ask a yes/no question:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
question(newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.getAnswer()
}
},
methods: {
getAnswer() {
if (this.question.indexOf('?') === -1) {
this.answer = 'Questions usually contain a question mark.'
return
}
this.answer = 'Thinking...'
var self = this
axios.get('https://yesno.wtf/api').then(response => {
self.answer = response.data.answer
}).catch(function(error) {
self.answer = 'Error! Could not reach the API. ' + error
})
}
}
})
</script>
</body>
</html>3
在这个示例中,使用 watch
选项允许我们执行异步操作 (访问一个 API),并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
计算属性 vs 侦听属性
侦听属性是Vue 提供的一种更通用的方式去观察和响应 Vue 实例上的数据变动。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch
——特别是如果你之前使用过 AngularJS。然而,通常更好的做法是使用计算属性而不是命令式的 watch
回调。
我们来看一个很简单的例子,快手前端实习生的面试题:两个输入框和一个显示框,计算两个输入框的和。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<input type="number" v-model="a">
<span>+</span>
<input type="number" v-model="b">
<span>=</span>
<span>{{ sum }}</span>
</div>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
a: 0,
b: 0,
sum: 0,
},
watch:{
a(value) {
this.sum = parseInt(value) + parseInt(this.b)
},
b(value) {
this.sum = parseInt(this.a) + parseInt(value)
}
}
})
</script>
</body>
</html>
上面代码是命令式且重复的。我们用计算属性的版本进行比较:
const app = new Vue({
el:'#app',
data:{
a: 0,
b: 0,
},
computed:{
sum(){
return parseInt(this.a) + parseInt(this.b)
}
}
})
好得多了,不是吗?
最后我们再回顾一下这节课的内容:计算属性是自动监听依赖值的变化,从而动态返回内容,监听是一个过程,在监听的值变化时,可以触发一个回调,并做一些事情。侦听属性watch中可以执行代码逻辑,如函数节流,Ajax异步获取数据,甚至操作 DOM。
最后
以上就是失眠仙人掌为你收集整理的5.Vue 计算属性和侦听器的全部内容,希望文章能够帮你解决5.Vue 计算属性和侦听器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复