首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Vue.js入门系列(三十七):`readonly` 与 `shallowReadonly`、`toRaw` 与 `markRaw`、`customRef`、`provide` 与 `inject

Vue.js入门系列(三十七):`readonly` 与 `shallowReadonly`、`toRaw` 与 `markRaw`、`customRef`、`provide` 与 `inject

作者头像
用户8589624
发布2025-11-14 09:24:16
发布2025-11-14 09:24:16
760
举报
文章被收录于专栏:nginxnginx

Vue.js入门系列(三十七):readonlyshallowReadonlytoRawmarkRawcustomRefprovideinject

引言

Vue 3 的响应式系统为开发者提供了更强大的工具,其中包括 readonlyshallowReadonlytoRawmarkRaw 以及 customRef 等 API,进一步增强了对响应式状态的控制。同时,provideinject 为组件间的依赖注入提供了简洁的方案。在本文中,我们将深入探讨这些新特性,了解它们的使用场景和方法。

一、readonlyshallowReadonly
1.1 什么是 readonly

readonly 是 Vue 3 提供的一个 API,用于创建只读的响应式对象。该对象本身是响应式的,但无法修改其属性值。任何修改操作都会被忽略,并且在开发环境下会发出警告。

代码语言:javascript
复制
import { readonly, reactive } from 'vue';

export default {
  setup() {
    const state = reactive({ name: 'John', age: 30 });
    const readonlyState = readonly(state);  // 创建只读副本

    readonlyState.name = 'Doe';  // 修改不会生效,且在开发模式下会发出警告

    return { readonlyState };
  }
};
1.2 什么是 shallowReadonly

shallowReadonlyreadonly 的浅层版本,它只会使第一层属性成为只读,而不对嵌套的对象进行处理。

代码语言:javascript
复制
import { shallowReadonly } from 'vue';

export default {
  setup() {
    const state = shallowReadonly({
      user: { name: 'Alice', age: 25 },
      isAdmin: true
    });

    state.isAdmin = false;  // 修改无效,且在开发环境下会发出警告
    state.user.name = 'Bob';  // 修改有效,因为是浅层只读

    return { state };
  }
};
1.3 使用场景
  • readonly:用于确保数据不会被误改,适合在传递数据到子组件时防止子组件直接修改状态。
  • shallowReadonly:用于对第一层属性进行只读保护,同时允许嵌套对象的属性可变。

二、toRawmarkRaw
2.1 什么是 toRaw

toRaw 是一个 Vue 3 的 API,它用于获取 reactivereadonly 对象的原始对象。通过 toRaw,我们可以绕过 Vue 的响应式系统,获取未被代理的原始数据。

代码语言:javascript
复制
import { reactive, toRaw } from 'vue';

export default {
  setup() {
    const state = reactive({ name: 'John', age: 30 });

    const rawState = toRaw(state);  // 获取原始对象
    console.log(rawState);  // 打印未代理的原始数据

    return { state, rawState };
  }
};
2.2 什么是 markRaw

markRaw 用于将对象标记为“非响应式对象”,即使将其传入 reactivereadonly,也不会被转换为响应式数据。

代码语言:javascript
复制
import { reactive, markRaw } from 'vue';

export default {
  setup() {
    const rawData = markRaw({ foo: 'bar' });
    const state = reactive({
      data: rawData  // 这里的 rawData 不会变成响应式
    });

    state.data.foo = 'baz';  // 不会触发响应式更新
    return { state };
  }
};
2.3 使用场景
  • toRaw:用于调试和处理一些性能问题,比如当不需要响应式时,直接操作原始数据。
  • markRaw:适合不希望某些对象成为响应式数据的场景,尤其是第三方库的数据对象或大型数据结构时,可以防止不必要的性能开销。

三、customRef
3.1 什么是 customRef

customRef 是 Vue 3 提供的一个用于创建自定义 ref 的 API。它允许开发者自定义 ref 的行为,控制数据的获取和设置时触发的响应式更新。

3.2 使用 customRef

通过 customRef,我们可以完全控制 ref 的依赖收集和更新过程。例如,可以使用它来实现防抖输入框的逻辑:

代码语言:javascript
复制
import { customRef } from 'vue';

function useDebouncedRef(value, delay = 300) {
  let timeout;
  return customRef((track, trigger) => {
    return {
      get() {
        track();  // 依赖收集
        return value;
      },
      set(newValue) {
        clearTimeout(timeout);
        timeout = setTimeout(() => {
          value = newValue;
          trigger();  // 触发更新
        }, delay);
      }
    };
  });
}

export default {
  setup() {
    const searchQuery = useDebouncedRef('', 500);  // 500ms 防抖

    return { searchQuery };
  }
};
3.3 使用场景
  • 自定义 ref 行为:当需要在 ref 的设置或获取过程中加入额外逻辑时(如防抖、节流等)。
  • 更精细的控制:用于对响应式更新的控制更加灵活,适用于需要高性能优化的场景。

四、provideinject
4.1 什么是 provideinject

provideinject 是 Vue 3 中的依赖注入机制,用于在祖先组件和后代组件之间传递数据。相比于通过 props 逐级传递数据,provideinject 更加简洁灵活,适用于跨层级组件通信。

4.2 使用 provide 传递数据

在祖先组件中,使用 provide 来提供数据:

代码语言:javascript
复制
import { provide } from 'vue';

export default {
  setup() {
    const theme = 'dark';
    provide('theme', theme);  // 提供名为 'theme' 的数据

    return {};
  }
};
4.3 使用 inject 接收数据

在后代组件中,使用 inject 来获取数据:

代码语言:javascript
复制
import { inject } from 'vue';

export default {
  setup() {
    const theme = inject('theme');  // 获取 'theme' 数据

    return { theme };
  }
};
4.4 provideinject 的使用场景
  • 跨组件通信:当需要在多个组件之间共享数据而无需通过 props$emit 时,provideinject 提供了一种轻量级的解决方案。
  • 依赖注入:适合在大型应用中使用,特别是在组件库或插件开发中,可以利用 provide 注入全局服务或配置。
五、总结

通过本文的学习,你应该掌握了以下关键点:

  • readonlyshallowReadonly:了解了如何创建只读的响应式对象,并学会在不同场景下选择全局或浅层只读。
  • toRawmarkRaw:学会了如何获取响应式对象的原始数据,以及如何标记对象为非响应式数据,以避免性能问题或不必要的响应式开销。
  • customRef:掌握了如何自定义 ref 的行为,特别是在需要对响应式数据进行精细控制的场景下。
  • provideinject:理解了依赖注入的机制,学会在跨层级组件之间传递数据,提升了数据共享的灵活性。

Vue 3 的这些新功能为开发者提供了更加灵活、可控的工具,帮助我们更好地管理和优化应用中的状态与数据传递。在接下来的博客中,我们将继续探索 Vue 3 的更多高级特性和实际应用场景。如果你有任何疑问或需要进一步讨论,欢迎在评论区留言。感谢你的阅读,期待在下一篇博客中继续与大家分享更多 Vue.js 和 Vue 3 的开发技巧与经验!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-09-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Vue.js入门系列(三十七):readonly 与 shallowReadonly、toRaw 与 markRaw、customRef、provide 与 inject
    • 引言
    • 一、readonly 与 shallowReadonly
      • 1.1 什么是 readonly?
      • 1.2 什么是 shallowReadonly?
      • 1.3 使用场景
    • 二、toRaw 与 markRaw
      • 2.1 什么是 toRaw?
      • 2.2 什么是 markRaw?
      • 2.3 使用场景
    • 三、customRef
      • 3.1 什么是 customRef?
      • 3.2 使用 customRef
      • 3.3 使用场景
    • 四、provide 与 inject
      • 4.1 什么是 provide 与 inject?
      • 4.2 使用 provide 传递数据
      • 4.3 使用 inject 接收数据
      • 4.4 provide 和 inject 的使用场景
    • 五、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档