Vue3 计算属性和侦听器
计算属性
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。
1 2 3 4
| <div id="computed-basics"> <p>Has published books:</p> <span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Vue.createApp({ data() { return { author: { name: 'John Doe', books: [ 'Vue 2 - Advanced Guide', 'Vue 3 - Basic Guide', 'Vue 4 - The Mystery' ] } } } })
|
对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性。
基本例子
1 2 3 4
| <div id="computed-basics"> <p>Has published books:</p> <span>{{ publishedBooksMessage }}</span> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| Vue.createApp({ data() { return { author: { name: 'John Doe', books: [ 'Vue 2 - Advanced Guide', 'Vue 3 - Basic Guide', 'Vue 4 - The Mystery' ] } } }, computed: { publishedBooksMessage() { return this.author.books.length > 0 ? 'Yes' : 'No' } } }).mount('#computed-basics')
|
计算属性缓存 vs 方法
我们可以将同样的函数定义为一个方法,而不是一个计算属性。从最终结果来说,这两种实现方式确实是完全相同的。然而,不同的是计算属性将基于它们的响应依赖关系缓存。
这意味着下面的计算属性将永远不会更新,因为 Date.now ()
不是响应式依赖:
1 2 3 4 5
| computed: { now() { return Date.now() } }
|
相比之下,每当触发重新渲染时,调用方法将始终会再次执行函数。
如果你不希望有缓存,请用 method
来替代。
计算属性的 Setter
计算属性默认只有 getter,不过在需要时你也可以提供一个 setter:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| computed: { fullName: { get() { return this.firstName + ' ' + this.lastName }, set(newValue) { const names = newValue.split(' ') this.firstName = names[0] this.lastName = names[names.length - 1] } } }
|
侦听器
Vue 通过 watch
选项提供了一个更通用的方法来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
1 2 3 4 5 6 7
| <div id="watch-example"> <p> Ask a yes/no question: <input v-model="question" /> </p> <p>{{ answer }}</p> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script> <script> const watchExampleVM = Vue.createApp({ data() { return { question: '', answer: 'Questions usually contain a question mark. ;-)' } }, watch: { question(newQuestion, oldQuestion) { if (newQuestion.indexOf('?') > -1) { this.getAnswer() } } }, methods: { getAnswer() { this.answer = 'Thinking...' axios .get('https://yesno.wtf/api') .then(response => { this.answer = response.data.answer }) .catch(error => { this.answer = 'Error! Could not reach the API. ' + error }) } } }).mount('#watch-example') </script>
|
计算属性 vs 侦听器
Vue 提供了一种更通用的方式来观察和响应当前活动的实例上的数据变动:侦听属性。
通常更好的做法是使用计算属性而不是命令式的 watch
回调。
1 2 3 4 5 6 7 8 9 10 11 12 13
| const vm = Vue.createApp({ data() { return { firstName: 'Foo', lastName: 'Bar' } }, computed: { fullName() { return this.firstName + ' ' + this.lastName } } }).mount('#demo')
|