响应式基础知识
声明响应式状态的两种方法
setup中返回方式
setup中放回函数或者reactive定义的响应式数组或者对象. 这种方式比较麻烦,不推荐使用
使用<script setup>
这种方法是利用构建工具帮我们简化了setup中返回的繁琐工作. 可以理解为<script setup>顶层的导入和声明的变量可以被同一组件的模板中直接使用,可以理解为模板中的表达式和<script setup>内的代码处于同一作用域.
响应式代理和原始对象
声明响应式变量
reactive定义响应式变量
只能对数组或者对象定义响应式变量
<script setup>
import { reactive } from 'vue';
const state = reactive({ count: 0 });
function increment() {
state.count++;
}
</script>
原始对象和响应式代理对象并不相等; 同一个原始对象返回的代理对象是相等的; 响应式对象的代理对象是本身;
const raw = {a: 1};
const proxyRaw = reactive(raw);
const proxyRaw2 = reactive(proxyRaw);
const proxyRaw3 = reactive(raw);
console.log('响应式代理 vs. 原始对象', raw === proxyRaw); // false
console.log('proxyRaw,proxyRaw2', proxyRaw2 === proxyRaw); // true
console.log('proxyRaw3,proxyRaw2', proxyRaw2 === proxyRaw3); // true
ref定义响应式变量
可以对任意值类型定义响应式变量
const count2 = ref(0);
console.log('count2', count2);
console.log('count2', count2.value);
const countObj = ref({count: 1});
console.log('countObj', countObj);
console.log('countObj', countObj.value);
解构
- reactive的解构 解构后将失去响应性, 传入函数内也将失去响应性, 意味着解构出来的变量变化将不会影响到原响应式对象.
const state = reactive({ count: 0 })
let n = state.count // n将失去响应性
n++
let { count } = state // count将失去响应性
count++
- ref的解构
模板中解构 ref作为模板渲染上下文的顶层属性时才会被自动解构.
const object = { foo: ref(1) }
const { foo } = object
// 模板中得到渲染结果为2
{{ foo + 1 }}
在响应式对象中解构 当一个ref被嵌套在响应式对象中,会自动解构,和一般属性一致
const count = ref(0)
const state = reactive({
count
})
console.log(state.count) // 0
state.count = 1
console.log(count.value) // 1
数组和集合类型的不会自动解构 当 ref 作为响应式数组或像 Map 这种原生集合类型的元素被访问时,不会进行解包。
局限性
reactive的局限性
- 仅对对象类型有效(对象,数组,Map,Set这样的集合类型), 但是对于string,number,boolean这样的原始类型无效
- 不能替换响应式对象的引用,否则响应式失效.
let state = reactive({ count: 0 })
// 上面的引用 ({ count: 0 }) 将不再被追踪(响应性连接已丢失!)
state = reactive({ count: 1 })
- 解构之后失去响应性
ref的局限性
- 解构之后失去响应性
const countObj = ref({count: 1});
// count失去了响应性
let {count} = countObj.value;
count++;
console.log('count', count, countObj.value.count);