Vue3-其它Composition API

shallowReactive和shallowRef

1. shallowReactive

  • 用于创建浅层响应式对象,仅处理第一层属性的响应式。当修改嵌套属性时不会触发更新
  • 适用于外层属性变化频繁但内层结构稳定的情况‌。如分页组件的查询参数对象
  • 使用shallowReactive可以提升性能‌

2. shallowRef

  • 主要用于基本数据类型,或替换整个对象而不是修改内部属性。
  • 当需要替换整个对象而不是修改其内部属性时,使用shallowRef更合适,如重置表单对象时整体替换
  • 可以避免不必要的深度响应式处理,提高性能‌,因为它不会追踪对象内部的变化,只关心.value引用变化‌

3.shallowReactive 和 shallowRef 都是针对特定场景设计的浅层响应式 API

const state = shallowReactive({ a: 1, nested: { b: 2 } });
state.a = 2; // 触发更新
state.nested.b = 3; // 不触发更新
const refObj = shallowRef({ x: 1 });
refObj.value = { x: 2 }; // 触发更新
refObj.value.x = 3;      // 不触发更新

4. 局限性‌:嵌套属性修改需通过触发外层变更(如对象替换)或配合其他 API(如 triggerRef)实现更新‌

readonly 与 shallowReadonly

1. readonly

  • ‌创建一个‌深度只读‌的代理对象,所有嵌套属性均不可修改,任何修改尝试会触发警告并阻止操作‌
  • 不可变全局配置‌:如应用的主题配置、权限规则等,确保数据不被意外修改‌
  • 传递只读数据‌:父组件传递数据给子组件时,防止子组件修改原始数据‌
const state = readonly({ a: 1, nested: { b: 2 } });
state.a = 2;       // 触发警告,不生效
state.nested.b = 3; // 触发警告,不生效

 2. shallowReadonly

  • 仅对对象的‌第一层属性‌设为只读,嵌套对象的属性仍可修改‌
  • 部分只读需求‌:仅需保护对象顶层属性,如分页参数中的页码(page)不可修改,但嵌套的查询条件(query)允许变动‌
  • 性能敏感场景‌:当数据嵌套层级较深时,避免递归代理带来的性能损耗‌
const state = shallowReadonly({ a: 1, nested: { b: 2 } });
state.a = 2;       // 触发警告,不生效
state.nested.b = 3; // 可正常修改

3. 开发环境警告‌:修改 readonly 或 shallowReadonly 对象的只读属性时,控制台会输出警告,生产环境无警告

4. 与响应式数据结合‌:两者可接受 reactive 或 ref 创建的响应式对象,返回只读代理‌

toRaw 与 markRaw‌

1. toRaw

  • 作用‌:获取由 reactive、readonly 等创建的响应式代理对象的原始非代理版本,解除响应式追踪‌
  • 返回值‌:返回原始对象,对该对象的修改不会触发视图更新‌
  • 性能优化‌:处理大型数据时,避免响应式追踪的开销(如大数据计算或遍历)‌
  • 第三方库集成‌:向不支持响应式系统的外部库传递原始数据‌
  • 仅作用于响应式代理对象,对普通对象调用会直接返回自身‌
  • 获取的原始对象不应长期引用,否则可能引发数据不一致问题‌
const state = reactive({ list: [/* 大量数据 */] });
const rawList = toRaw(state.list); // 避免响应式代理的性能损耗

2. markRaw

  • ‌作用‌:标记一个对象,使其永远不会被转换为响应式代理,即使被嵌套在响应式对象中‌
  • 返回值‌:返回被标记的原始对象本身‌
  • 静态数据标记‌:如第三方类库实例、工具类对象或固定配置数据‌
  • 不可变数据渲染‌:渲染大型不可变列表时,跳过响应式转换以提升性能‌
  • 被标记对象的嵌套属性可能被响应式系统追踪(除非手动递归标记)‌
  • 修改被标记对象的属性不会触发更新,但直接替换整个对象会触发响应‌
const helper = markRaw(new HelperClass()); // 工具类无需响应式
const state = reactive({ helper });

customRef 

  • customRef 是 Vue3 提供的用于‌创建自定义响应式引用‌的 API,允许开发者显式控制依赖追踪(track)和更新触发(trigger)
  • 适用于需要精细化控制响应式逻辑的场景‌
  • customRef 默认不自动追踪依赖,需手动调用 track() 和 trigger() 以提升性能‌
  • 防抖示例
import { customRef } from 'vue';

function debouncedRef(initialValue, delay = 500) {
  let timeout;
  return customRef((track, trigger) => ({
    get() {
      track();  // 追踪依赖
      return initialValue;
    },
    set(newValue) {
      clearTimeout(timeout);
      timeout = setTimeout(() => {
        initialValue = newValue;
        trigger();  // 触发更新
      }, delay);
    }
  }));
}
const keyword = debouncedRef(''); // 使用防抖 Ref
  • 异步操作(如接口请求)完成后触发更新‌示例
function asyncRef(url) {
  let data = null;
  return customRef((track, trigger) => ({
    get() {
      track();
      return data;
    },
    async set() {
      const res = await fetch(url);
      data = await res.json();
      trigger();
    }
  }));
}

provide 与 inject

  • provide 与 inject 是 Vue3 提供的‌跨层级组件通信 API‌,允许祖先组件向任意后代组件直接传递数据或方法,无需通过中间组件逐层传递 Props‌
  • Vue3 在组件实例中通过 _provided 属性存储 provide 提供的数据‌。 inject 从当前组件向上递归查找祖先组件的 _provided 属性,匹配键名获取数据‌
  • provide‌:在父组件中定义需提供的数据或方法
// 父组件(祖先)
import { ref, provide } from 'vue';

setup() {
  //默认情况下provide 提供的数据‌非响应式‌,需通过 ref 或 reactive 包装以实现响应式更新‌
  const message = ref('Hello'); 
  provide('messageKey', message); // 提供响应式数据
}
  • inject‌:在后代组件中接收注入的数据或方法‌
// 后代组件(如孙子)
import { inject } from 'vue';

setup() {
  const message = inject('messageKey'); // 接收数据
  return { message };
}

响应式数据的判断

  • isRef‌ 判断一个值是否为 ref 定义的响应式数据
import { ref, isRef } from 'vue';
const count = ref(0);
console.log(isRef(count)); // true ‌
  • isReactive‌ 检查对象是否由 reactive 创建的响应式代理
import { reactive, isReactive } from 'vue';
const obj = reactive({ name: 'Vue' });
console.log(isReactive(obj)); // true ‌

const plainObj = { name: 'Vue' };
console.log(isReactive(plainObj)); // false ‌
  • isReadonly‌ 判断对象是否由 readonly 创建的只读代理
import { reactive, readonly, isReadonly } from 'vue';
const original = reactive({ name: 'Vue' });
const copy = readonly(original);
console.log(isReadonly(copy)); // true ‌
  • isProxy‌ 检测对象是否由 reactive 或 readonly 创建的代理(包括 shallowReactive 和 shallowReadonly)
import { reactive, isProxy } from 'vue';
const obj = reactive({ name: 'Vue' });
console.log(isProxy(obj)); // true ‌
const obj = readonly(reactive({ name: 'Vue' }));
console.log(isProxy(obj)); // true
console.log(isReactive(obj)); // false ‌
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值