我是靠谱客的博主 失眠仙人掌,最近开发中收集的这篇文章主要介绍5.Vue 计算属性和侦听器,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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 计算属性和侦听器所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(58)

评论列表共有 0 条评论

立即
投稿
返回
顶部