Vue 学习笔记 —— 计算属性与监听器(三)

522 阅读2分钟

「这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战」。

1. 计算属性

1. 基础用法

对于一些复杂的逻辑计算,Vue 提供了计算属性,以下是一个简单的例子:

<div id="root">
    加数1:
    <button @click="add(1)"></button>
    <button @click="min(1)"></button>
    <br />
    加数2:
    <button @click="add(0)"></button>
    <button @click="min(0)"></button>
    <h3>{{num1}}+{{num2}}={{sum}}</h3>
</div>
const vm = new Vue({
    el: '#root',
    data: {
        num1: 2,
        num2: 3,
    },
    methods: {
        add(flag) {
            if (flag) {
                this.num1++;
            } else {
                this.num2++;
            }
        },
        min(flag) {
            if (flag) {
                this.num1--;
            } else {
                this.num2--;
            }
        },
    },
    computed: {
        sum: {
            get() {
                return this.num1 + this.num2;
            },
            set(value) {
                console.log('set被调用');
                this.num1 = 0;
                this.num2 = value - this.num1;
            },
        },
    },
});

以上代码,定义了一个计算属性sum,由data中的num1num2相加而来。

  • 当初次读取时,sum中的getter就会被调用,返回值作为sum的值。
  • 当所依赖的数据发生变化时,sum中的getter也会被调用,返回值作为sum的值。
  • 当修改sum时,sum中的setter会被调用。

2. 简写形式

若不使用setter函数,可以简写为如下形式,方法名sum作为计算属性名,函数作为原来的getter函数。

computed: {
    sum() {
        return this.num1 + this.num2;
    },
}

3. 缓存

计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要num1num2还没有发生改变,多次访问sum,计算属性会立即返回之前的计算结果,而不必再次执行函数。

这也同样意味着下面的计算属性将不再更新,因为Date.now()不是响应式依赖

computed: {
    now() {
        return Date.now();
    },
}

2. 侦听器

1. 基础用法

<div id="root">
	<h2>当前模式:{{mode}}</h2>
	<button @click="changeMode">切换模式</button>
</div>
const vm = new Vue({
	el: '#root',
	data: {
		isDark: true,
		mode: '黑暗模式',
	},
	methods: {
		changeMode() {
			this.isDark = !this.isDark;
		},
	},
	watch: {
		isDark: {
			// 初始化时调用handler一次
			immediate: true,
			//handler什么时候调用?当isDark发生改变时。
			handler(newValue, oldValue) {
				console.log(newValue, oldValue);
				this.mode = this.isDark ? '黑暗模式' : '白天模式';
			},
		},
	},
});

定义了一个侦听器,侦听isDark属性,当isDark发生变化时,调用handler函数。

添加immediate: true,让 Vue 初始化时自动先调用一次handler函数。

当需要在数据变化时执行异步开销较大的操作时,侦听器非常有用。

2. 另一种写法

通过对示例对象vm来定义一个侦听器

vm.$watch('isDark', {
	// 初始化时调用handler一次
	immediate: true,
	handler(newValue, oldValue) {
		console.log(newValue, oldValue);
		this.mode = this.isDark ? '黑暗模式' : '白天模式';
	},
});

3. 深度监视

Vue 中的watch默认不监测对象内部值的改变,这并不代表 Vue 不能监测对象内部值的改变!

配置deep:true可以监测对象内部值的改变。

watch: {
    obj: {
        immediate: true,
        deep: true, // 开启深度监视
        handler(newValue, oldValue) {},
    },
},

4. 简写形式

watch: {
    isDark(newValue, oldValue) {}
},
vm.$watch('isDark', (newValue, oldValue) => {});