这个术语在今天的各种编程讨论中经常出现,但人们说它的时候究竟是想表达什么意思呢?本质上,响应性是一种可以使我们声明式地处理变化的编程范式。一个经常被拿来当作典型例子的用例即是 Excel 表格:
这里单元格 A2 中的值是通过公式 = A0 + A1 来定义的 (你可以在 A2 上点击来查看或编辑该公式),因此最终得到的值为 3,正如所料。但如果你试着更改 A0 或 A1,你会注意到 A2 也随即自动更新了。
而 JavaScript 默认并不是这样的。如果我们用 JavaScript 写类似的逻辑:
let A0 = 1
let A1 = 2
let A2 = A0 + A1
console.log(A2) // 输出结果 3
A0 = 2
console.log(A2) // 输出结果依然是 3
当我们更改 A0 后,A2 不会自动更新。
那么我们如何在 JavaScript 中做到这一点呢?首先,为了能重新运行计算的代码来更新 A2,我们需要将其包装为一个函数:
let A2
function update() {
A2 = A0 + A1
}
然后,我们需要定义几个术语:
我们需要一个魔法函数,能够在 A0 或 A1 (这两个依赖) 变化时调用 update() (产生作用)。
whenDepsChange(update)
这个 whenDepsChange() 函数有如下的任务:
可用data选项来声明组件的响应式状态;该data选项的值应为返回一个对象的函数;
data函数返回对象的所有顶层属性都会被代理到组件实例(即方法和生命周期钩子中的 this)上
<script>
export default {
// data 选项的值应该是一个函数返回的对象
data: () => ({
account: 'Abc',
user: {
name: 'Mike',
age: 22
}
}),
methods: {
changeAccount() {
// 取出数据源可通过 this(当前组件得实例对象) 关键字获取
this.account += '='
},
changeUser() {
this.user.age ++
}
}
}
</script>
<template>
<h2>账号:{{ account }}</h2>
<button @click="changeAccount">点我更改账号</button>
<hr>
<h2>用户:{{ user}}</h2>
<button @click="changeUser">点我更改用户信息</button>
</template>
如果在组合式 API 中直接声明普通变量的数据源,他们并不具备响应式数据
<script setup>
// 普通的变量不具备响应式
let account = 123
function changeAccount() {
account+= 1
console.log(account)
}
// 普通类型的对象,不具备响应式
let emp = {
salary: 7000,
name: 'Annie'
}
function changeEmpSalary() {
emp.salary += 100
console.log(emp)
}
</script>
<template>
<h1>账号:{{ account }}</h1>
<button @click="changeAccount">点我更改账号</button>
<hr>
<h1>员工:{{ emp }}</h1>
<button @click="changeEmpSalary">点我更改薪资</button>
</template>
用num.value=***来修改值
获取数据值的时候需要加.value。可以理解为ref是通过reactive包装了一层具有value属性的对象实现的
参数可以传递任意数据类型,传递对象类型时也能保持深度响应式,所以适用性更广,setup中定义数据时推荐优先使用ref,方便逻辑拆分和业务解耦
template中使用ref值不用通过value获取(导出后已默认做了一个解构),js中使用ref必须通过.value获取
ref获取元素
<script setup>
// 引入 ref 函数,来声明响应式对象
import { ref } from 'vue'
// 使用 ref 函数来声明原始类型的数据源,具备响应式
let account = ref('Abc')
// 更改账号,控制台查看最新值
function changeAccount() {
// 通过 ref 函数声明的响应式数据,需要使用 .value 来获取数据的值
account.value += '='
console.log(account)
}
// 使用 ref 函数来声明对象类型的数据源:具备响应式
let emp = ref({
salary: 7000,
name: 'Jack'
})
// 更改员工薪资,控制台查看最新值
function changeEmpSalary() {
// 通过 ref 函数声明的响应式数据,需要使用 .value 来获取数据的值
emp.value.salary += 100
console.log(emp)
}
</script>
<template>
<h1>账号:{{ account }}</h1>
<button @click="changeAccount">点我更改账号</button>
<hr>
<h1>员工:{{ emp }}</h1>
<button @click="changeEmpSalary">点我更改员工薪资</button>
</template>
reactive()函数只对对象类型有效(对象、数组、Map、Set),对string、number和 boolean这样的原始类型无效
reactive接收一个普通对象然后返回该普通对象的响应式代理
<script setup>
// 引入 reactive 函数
import { reactive } from 'vue'
// reactive 对原始类型是无效(不具备响应式)
let account = reactive('Abc')
function changeAccount() {
account += '='
console.log(account)
}
// reactive 对象数据源(具有响应式)
let emp = reactive({
name: 'Jack',
salary: 7000
})
function changeEmpSalary() {
emp.salary += 1
console.log(emp)
}
</script>
<template>
<hr>
<h1>账号:{{ account }}</h1>
<button @click="changeAccount">点我更改账号</button>
<hr>
<h1>员工:{{ emp }}</h1>
<button @click="changeEmpSalary">点我更改员工薪资</button>
</template>
本文介绍了Vue3.0 选项式api和组合式api的响应式数据以及部分写法,希望对你的阅读学习有所帮助。