基础三、 计算属性、侦听器和Class 与 Style 绑定

在上篇中介绍了模板语法、Data Property 和方法。本节的计算属性和侦听器非常有用。

一、计算属性

1.任何包含响应式数据的复杂逻辑,都应该使用计算属性。模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。

 1 <template>
 2   <div id="computed-basics">
 3     <p>Has published books:</p>
 4     <span>{{ publishedBooksMessage }}</span>
 5   </div>
 6 </template>
 7 <script>
 8 export default {
 9   data() {
10     return {
11       author: {
12         name: "John Doe",
13         books: [
14           "Vue 2 - Advanced Guide",
15           "Vue 3 - Basic Guide",
16           "Vue 4 - The Mystery",
17         ],
18       },
19     };
20   },
21   computed: {
22     // 计算属性的 getter
23     publishedBooksMessage() {
24       // `this` 指向 vm 实例
25       return this.author.books.length > 0 ? "Yes" : "No";
26     },
27   },
28 };
29 </script>
View Code

这里声明了一个计算属性 publishedBooksMessage。尝试更改应用程序 data 中 books 数组的值,你将看到 publishedBooksMessage 如何相应地更改。你可以像普通属性一样将数据绑定到模板中的计算属性。Vue 知道 vm.publishedBookMessage 依赖于 vm.author.books,因此当 vm.author.books 发生改变时,所有依赖 vm.publishedBookMessage 的绑定也会更新。

以上计算属性的原理是什么?
1. data 属性初始化 getter setter
2. computed 计算属性初始化,提供的函数将用作属性 reversedMessage 的 getter
3. 当首次获取 reversedMessage 计算属性的值时,Dep 开始依赖收集
4. 在执行 message getter 方法时,如果 Dep 处于依赖收集状态,则判定 message 为reversedMessage 的依赖,并建立依赖关系
5. 当 message 发生变化时,根据依赖关系,触发 reverseMessage 的重新计算

详情请看https://segmentfault.com/a/1190000010408657

2.计算属性对比方法

在以上例子中,调用方法达到同样的效果。但是不同的是计算属性是基于它们的反应依赖关系缓存的。计算属性只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 author.books 还没有发生改变,多次访问 publishedBookMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。使用缓存是为了提高性能,如果不希望有缓存,直接用 method 来替代就可以了。

计算属性默认只有 getter,不过在需要时你也可以提供一个 setter:

 1 computed: {
 2   fullName: {
 3     // getter
 4     get() {
 5       return this.firstName + ' ' + this.lastName
 6     },
 7     // setter
 8     set(newValue) {
 9       const names = newValue.split(' ')
10       this.firstName = names[0]
11       this.lastName = names[names.length - 1]
12     }
13   }
14 }

二、侦听器

 当需要在数据变化时执行异步或开销较大的操作时,使用侦听器。请看示例:

 1 <template>
 2   <div>
 3     <p>
 4       Ask a yes/no question:
 5       <input v-model="question" />
 6     </p>
 7     <p>{{ answer }}</p>
 8   </div>
 9 </template>
10 <script>
11 export default {
12   data() {
13     return {
14       question: "",
15       answer: "Questions usually contain a question mark. ;-)",
16     };
17   },
18   watch: {
19     // whenever question changes, this function will run
20     question(newQuestion, oldQuestion) {
21       if (newQuestion.indexOf("?") > -1) {
22         this.getAnswer();
23       }
24     },
25   },
26   methods: {
27     getAnswer() {
28       this.answer = "Thinking...";
29       axios
30         .get("https://yesno.wtf/api")
31         .then((response) => {
32           this.answer = response.data.answer;
33         })
34         .catch((error) => {
35           this.answer = "Error! Could not reach the API. " + error;
36         });
37     },
38   },
39 };
40 </script>
View Code

使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

计算属性和侦听器的对比:

  依赖 是否有缓存 开销 觖发方式 使用场景
methods 外部调用 事件或者函数的回调,被动调用 每次确实需要重新加载,不需要缓存时,需要参数时
compled 依赖追踪属性值的改变,响应式依赖 小,快 在html渲染开始,自动触发

改变一个变量的显示,数据量大,需要缓存的时候。命令式且重复的的数据,复杂的渲染数据计算,多处需要引用的变量计算。比如表单校验

watch 依赖追踪属性值的改变 大,差 on这种触发 异步操作,Ajax,操作时

 三、Class与Style绑定

表达式结果的类型除了字符串之外,还可以是对象或数组。

1.对象绑定语法

:class="{ active: isActive }",也可以:class="{ active: isActive, 'text-danger': hasError }" 然后结合以下代码实现:

1 data() {
2   return {
3     isActive: true,
4     hasError: false
5   }
6 }

 此外,还可以通过computed 属性实现。

2.数组的语法

:class="[activeClass, errorClass]",如果变量值为'active','text-danger'渲染的结果为:<div class="active text-danger"></div>
3.在组件上使用
1 <my-component class="baz boo"></my-component>或者<my-component :class="{ active: isActive }"></my-component>

4.绑定内联样式

style样式绑定跟class基本类型。:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名。

在 :style 中使用需要 (浏览器引擎前缀) vendor prefixes 的 CSS property 时,如 transform,Vue 将自动侦测并添加相应的前缀。

这样写只会渲染数组中最后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex

   1 <div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>  
原文地址:https://www.cnblogs.com/EastWind/p/14597478.html