响应性是指数据的修改会自动同步更新视图效果。其中也包括其他的数据同步,比如computed、watch、vuex等,但数据的同步不一定就是具有响应性,体现响应性的效果最终应该回到数据的更新会自动更新视图这点上,这个自动过程是因为框架实现了MVVM模型的VM,原本是MVC,也就是VM看作C,获取数据并操作视图这些大量繁琐过程自动化了,从而减少开发操作DOM的工作量。
Vue3
ref
示例一
简单了解一下概念的来源,然后了解基础用法,这里使用Vue3作为示例代码。
来看一段奇怪的代码:
<script setup>
import {ref} from 'vue';
let count = ref(0);
let total = 0;
function onAddClick() {
count.value++;
total++;
}
</script>
<template>
<div>count:{{ count }}</div>
<div>total:{{ total }}</div>
<button @click="onAddClick">+</button>
</template>
当点击+按钮的时候,发现在视图上不仅count更新了,total也更新了,这里是因为count是响应性变量,count的修改触发视图的更新,而视图的更新以一个Vue组件为单位进行更新,所以total视图也更新了。所以在开发中有时会出现非响应性变量也能更新,有时误以为这个变量也具有响应性。
从这个例子知道,一个变量在视图的更新了但这个变量可能并非是响应性变量,在实际开发中会更复杂一些,需要知道数据的修改会不会触发视图更新,因为把非响应性变量当做响应性变量会出现视图未更新的情况。但有一点能确定的是,响应性变量的修改最终和模板关联,那么就会以这个组件单位更新视图。而如果组件内定义了响应性变量但没和模板关联,那么并不会触发视图更新。比如以下代码:
<script setup>
import {ref} from 'vue';
let count = ref(0);
let total = 0;
function onAddClick() {
count.value++;
total++;
}
</script>
<template>
<!-- <div>count:{{ count }}</div>-->
<div>total:{{ total }}</div>
<button @click="onAddClick">+</button>
</template>
示例二
来看一下这段代码的打印结果:
<script setup>
import {ref} from 'vue';
let count = ref(0);
function onAddClick() {
count.value++;
console.log('count', count)
console.log('count value', count.value)
}
</script>
<template>
<div>count:{{ count }}</div>
<button @click="onAddClick">+</button>
</template>
可以看到count变量是通过RefImpl new出来的,实际的值在value属性上。
computed
<script setup>
import {computed, ref} from 'vue';
let count = ref(0);
const total = computed(() => {
return count.value + 1;
})
function onAddClick() {
count.value++;
}
</script>
<template>
<div>count:{{ count }}</div>
<div>total:{{ total }}</div>
<button @click="onAddClick">+</button>
</template>
这段代码中的total是正常触发视图更新,而下面这段代码并不会:
<script setup>
import {computed, ref} from 'vue';
let count = ref(0);
let pureCount = 0;
const total = computed(() => {
return pureCount + 1;
})
function onAddClick() {
pureCount++;
}
</script>
<template>
<div>count:{{ count }}</div>
<div>total:{{ total }}</div>
<button @click="onAddClick">+</button>
</template>
total是Ref类型,当依赖的响应性变量值修改了,会触发重新计算,而method是当视图更新了就会触发。
watch
<script setup>
const x = ref(0);
const y = ref(0)
// 单个 ref
watch(x, (newX) => { console.log(`x is ${newX}`) })
// getter 函数
watch( () => x.value + y.value, (sum) => {
console.log(`sum of x + y is: ${sum}`)
})
// 多个来源组成的数组
watch([x, () => y.value], ([newX, newY]) => {
console.log(`x is ${newX} and y is ${newY}`)
})
</script>
hook
官方文档对hook的介绍:cn.vuejs.org/guide/reusa…
hook函数也叫做组合式函数,和函数相比的区别在于hook函数是有状态的复用。这里的有状态、无状态是什么意思呢?
- 无状态:是指每次调用函数,前一次的调用后不会影响下一次的调用,每次调用的效果是相互独立的
- 有状态:可能调用的效果会相互影响 hook函数通常是有状态的,hook函数通常也是有副作用的,这点官方文档没有说明,有副作用是指如果不了解hook所依赖的状态及转换是怎样的,可能会有意外的效果。
大部分的hook函数功能通过普通函数也可以实现,但在和框架的结合程度上不如hook函数。hook函数的目的是为了在框架上更简洁而设计的函数。