响应式

120 阅读2分钟

响应式基础知识

声明响应式状态的两种方法

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的局限性

  1. 仅对对象类型有效(对象,数组,Map,Set这样的集合类型), 但是对于string,number,boolean这样的原始类型无效
  2. 不能替换响应式对象的引用,否则响应式失效.
let state = reactive({ count: 0 })

// 上面的引用 ({ count: 0 }) 将不再被追踪(响应性连接已丢失!)
state = reactive({ count: 1 })
  1. 解构之后失去响应性

ref的局限性

  1. 解构之后失去响应性
const countObj = ref({count: 1});
// count失去了响应性
let {count} = countObj.value;
count++;
console.log('count', count, countObj.value.count);