2.响应式基础

146 阅读3分钟

Proxy(代理)

proxy主要是创建一个对象的代理,从而实现基本操作的拦截和自定义

reactive 响应式对象

  • 使用方式
  1. 在setup()中使用,需要将变量return出去才可以在模板中使用
  2. 在< script setup >使用,可以直接在模板中使用
  3. reactive的返回值是一个原始对象的Proxy,返回值与他所代理的原始对象并不是全等的
  4. 为了保证代理的一致性,对同一个原始对象调用reactive,总是返回同样的代理对象
  5. 对一个代理对象调用reactive,返回的也总是他的本身
  6. reactive的响应式深层次的,以上两条规则,对嵌套的对象也是适用的
  7. 可以定义简单的数据类型,也能在模板中使用,但是会警告,所以不建议这样使用
// 验证3 4 5
const obj = {}
const proxy = reactive(obj)
console.log(obj === proxy); // false
const proxy1 = reactive(obj)
console.log(proxy === proxy1); // true
const proxy2 = reactive(proxy1)
console.log(proxy1 === proxy2); // true
// 验证6
const raw = {}
proxy.a = raw
console.log(proxy.a === raw); // false
  • 局限性
  1. 仅对对象类型有效(包括数组、对象、Map、Set)
  2. 不可随意替换一个响应式对象,会导致初始对象的响应式连接丢失;因为vue的响应式系统是根据属性追踪的,需要保持该响应式对象始终是相同的引用
// 验证2
let o = { count: 0 }
let state = reactive(o)
let p = {count :777}
state = reactive(p)
o.count = 888 
console.log(state.count); // 777
p.count = 999 
console.log(state.count); // 999

ref 响应式变量

  • 使用方式
  1. 在setup()中使用,需要将变量return出去才可以在模板中使用
  2. 在< script setup >使用,可以直接在模板中使用
  3. ref()方法来允许我们创建可以使用任何值类型的响应式ref
  4. ref将传入的参数包裹成一个带有.value属性的ref对象,在script中通过访问.value属性获取该值,
  5. 当传入的参数为一个对象类型时,会用reactive()自动转换他的.value为proxy代理
  6. ref被传递给函数或者在对象上被解构时,都不会丢失他的响应式
const obj1 = {
  foo: ref(1),
  bar: ref(2)
}
// 该函数接收一个 ref
// 需要通过 .value 取值
// 但它会保持响应性
console.log(obj1.foo);  // ref对象,通过 .value 取值
// 仍然是响应式的
const { foo, bar } = obj1
console.log(foo.value); // 1
  • 在模板中的使用(解包)
  1. 在模板中,当变量作为顶层属性被访问时,会自动解包,不需要使用.value
  2. 在模板中,当变量不是作为顶层属性时,分为以下情况
  3. ref在响应式对象reactive中的解包,会自动解包,不需要使用.value
  4. 如果一个响应式对象中的属性已经关联了一个ref,一个新的ref赋值会直接替换掉旧的ref
// 验证1
//script
const count = ref(1)
//template
<div>{{ count }}</div>
// 验证2
//script
const obj1 = {
  foo: ref(1),
  bar: ref(2)
}
// 通过解构赋值将foo提升为顶层属性
const { foo, bar } = obj1
//template
<!-- 直接获取值,自动解包 1-->
<div>{{ obj1.foo }}</div> 
<!-- 作为表达式使用无法自动解包,会编译为[object Object]1 -->
<div>{{ obj1.foo + 1 }}</div>
<!-- 正常编译 2-->
<div>{{ obj1.foo.value + 1 }}</div>
<!-- 解构赋值提升顶层属性 1-->
<div>{{ foo }}</div>
// 验证3
const aa = ref(1)
const bb = reactive({
  aa
})
console.log(bb.aa); // 1
bb.aa = 2
console.log(aa.value); // 2
// 验证4
const aa = ref(1)
const bb = reactive({
  aa
})
console.log(bb.aa); // 1
console.log(aa.value); // 1
const cc = ref(3)
bb.aa = cc
console.log(bb.aa);// 3
console.log(aa.value); // 1