VueUse 是怎么封装Vue3 Provide/Inject 的?

这篇具有很好参考价值的文章主要介绍了VueUse 是怎么封装Vue3 Provide/Inject 的?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Provide/Inject

Provide 和 Inject 可以解决 Prop 逐级透传问题。注入值类型不会使注入保持响应性,但注入一个响应式对象,仍然有响应式的效果。

Provide 的问题是无法追踪数据的来源,在任意层级都能访问导致数据追踪比较困难,不知道是哪一个层级声明了这个或者不知道哪一层级或若干个层级使用了。

看看 VueUse 的 createInjectionState 是怎么封装 Provide 的,并且怎么避免 Provide 的问题。

介绍

createInjectionState:创建可以注入组件的全局状态。

//useCounterStore.ts
const [useProvideCounterStore, useCounterStore] = createInjectionState(
  (initialValue: number) => {
    // state
    const count = ref(initialValue)

    // getters
    const double = computed(() => count.value * 2)

    // actions
    function increment() {
      count.value++
    }

    return { count, double, increment }
  })

export { useProvideCounterStore }
// If you want to hide `useCounterStore` and wrap it in default value logic or throw error logic, please don't export `useCounterStore`
export { useCounterStore }
<!-- RootComponent.vue -->
<script setup lang="ts">
  import { useProvideCounterStore } from './useCounterStore'

  useProvideCounterStore(0)
</script>

<template>
  <div>
    <slot />
  </div>
</template>
<!-- CountComponent.vue -->
<script setup lang="ts">
import { useCounterStore } from './useCounterStore'

// use non-null assertion operator to ignore the case that store is not provided.
const { count, double } = useCounterStore()!
// if you want to allow component to working without providing store, you can use follow code instead:
// const { count, double } = useCounterStore() ?? { count: ref(0), double: ref(0) }
// also, you can use another hook to provide default value
// const { count, double } = useCounterStoreWithDefaultValue()
// or throw error
// const { count, double } = useCounterStoreOrThrow()
</script>

<template>
  <ul>
    <li>
      count: {{ count }}
    </li>
    <li>
      double: {{ double }}
    </li>
  </ul>
</template>

源码

/**
 * Create global state that can be injected into components.
 *
 * @see https://vueuse.org/createInjectionState
 *
 */
export function createInjectionState<Arguments extends Array<any>, Return>(
  composable: (...args: Arguments) => Return,
): readonly [useProvidingState: (...args: Arguments) => Return, useInjectedState: () => Return | undefined] {
  const key: string | InjectionKey<Return> = Symbol('InjectionState')
  const useProvidingState = (...args: Arguments) => {
    const state = composable(...args)
    provide(key, state)
    return state
  }
  const useInjectedState = () => inject(key)
  return [useProvidingState, useInjectedState]
}

思考

为什么返回的是数组

createInjectionState 返回的数组,使用 demo 中采用的数组解构的方式。那么数组解构和对象解构有什么区别么?

提到数组解构首先想到的是 react 的 useState。

const [count,setCount] =useState(0)

之所以用数组解构是因为在调用多个 useState 的时候,方便命名变量。

const [count,setCount] =useState(0)
const [double, setDouble] = useState(0);

如果用对象解构,代码会是

const {state:count,setState:setCount} =useState(0)
const {state:double, setState:setDouble} = useState(0);

相比之下数组显得代码更加简洁。

数组解构也有缺点:返回值必须按顺序取值。返回值中只取其中一个,代码就很奇怪。

const [,setCount] =useState(0)

因此数组解构时适合使用所有返回值,并且多次调用方法的情况;对象解构适合只使用其中部分返回值,并且一次调用方法的情况。

createInjectionState 创建的注入状态 key 是 Symbol('InjectionState'),也就是每次运行的 key 都不一样,有可能多次调用 createInjectionState,因此 createInjectionState 采用数组解构的方式。但使用返回值可能只使用 useInjectedState,所有在 useCounterStore.ts 中又将 useProvideCounterStore 和 useInjectedState 以对象的方式导出避免出现下面奇怪的写法。

const [,useCounterStore] =useCounterStore()

使用例子中的 state 结构

使用案例中将 provide 中的对象分为 state、getters、actions。结构很想 vuex,而 useProvideCounterStore 相当于 vuex 中的 mutation。采用这种结构是因为 provide 的缺点:无法追踪数据的来源,在任意层级都能访问导致数据追踪比较困难,不知道是哪一个层级声明了这个或者不知道哪一层级或若干个层级使用了。

采用类似 vuex 的结构能相对比较好的追踪状态。

 // state
  const count = ref(initialValue)

  // getters
  const double = computed(() => count.value * 2)

  // actions
  function increment() {
    count.value++
  }

readonly

createInjectionState 返回的数组是 readonly 修饰的,useInjectedState 返回的对象并没有用 readonly 修饰,provide/inject 的缺点就是状态对象不好跟踪,容易导致状态变更失控。既然提供了 useProvidingState 修改状态的方法,useInjectedState 返回的状态如果是只读的能更好防止状态变更失控。文章来源地址https://www.toymoban.com/news/detail-435707.html

到了这里,关于VueUse 是怎么封装Vue3 Provide/Inject 的?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue3的组合式API中如何使用provide/inject?

    听说 Vue 3 加入了超多酷炫的新功能,比如组合式 API 等等。今天我们就来聊聊 Vue 3 中的组合式 API,并且如何使用 provide/inject 来搞定它! 首先,我们来了解一下组合式 API 是什么。其实,组合式 API 就是一个用来构建和组合函数的工具,它能让我们的代码更加简洁、可读性更

    2024年02月11日
    浏览(42)
  • 【vue3】vue3的三种写法(附带provide/inject、toRefs说明、ref,reactive的区别)

    写法一(vue3的写法) toRefs定义: toRefs可以将对象(只能接收rective对象)中的属性变成响应式。 正常reactive对象数据也是响应式的,如果用toRefs解构出去会更加方便。 toRefs什么时候用? 数据量如果很多, 我们一般会用解构来简化代码, 那么在vue3 中如果使用对象的解构,

    2024年02月13日
    浏览(44)
  • VUE2中provide 和 inject用法,以及怎么做响应式数据?

    provide 和 inject, 用来实现实现跨组件之间通信. 父子/孙子组件之间任意通信. 在祖先组件中通过provide注入一个依赖,不论组件层次有多深,都可以通过inject 来访问到provide的数据. 三个组件: Home组件 - Provide组件 - Sun组件(最底层) 在provide 组件中: 在sun组件中: 这时页面上就会展示

    2024年02月16日
    浏览(32)
  • vue学习,使用provide/inject通信

    提示:组件的provide,可以被其内所有层级的组件,通过inject引用 需求:使用provide/inject通信 1、AA.vue 2、BB.vue 3、CC.vue 4、DD.vue AA组件引用BB组件 BB组件引用CC组件 CC组件引用DD组件 BB、CC、DD都可以通过 inject 获取到AA的 provide provide与inject之间的通讯,既可以传输数据,也可以传

    2024年01月18日
    浏览(53)
  • vue2.x中的provide和inject用法

    父子通信 兄弟通信 跨级通信 1、类型 2、详细 3、示例 爷组件 父组件 孙组件 对比一下前后差异:无论点击多少次,孙组件中的诞生于 year 字段永远都是1995 并不会发生变化,通过 方式1、方式2、方式4传值是可以响应的。 正是官网所提到的: provide 和 inject 绑定并不是可响应

    2024年02月05日
    浏览(43)
  • 【Vue】父子组件传参 && 孙子调用爷爷的方法 provide inject

    一. 父传子 父组件先在data中定义要传给子组件的属性名 父组件在中引入子组件 在components中注册 使用步骤 3 中注册好的子组件 在 3 中,父传子 (1)利用 : 将父组件的对象、数组、字符串等传给子组件,供子组件使用 (2)利用 @ 将父组件的方法传给子组件,供子组件调用

    2024年02月08日
    浏览(48)
  • vue祖孙组件通信传值 provide 与 inject 以及 数据的响应式

    通常,当我们需要从父组件向子组件传递数据时,我们使用 props。但是对于一些深度嵌套的组件,深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 prop 沿着组件链逐级传递下去,可能会很麻烦。 provide 和 inject无论组件层次结构有多深,父组件都可以作为其

    2024年02月14日
    浏览(36)
  • Vue 中的依赖注入,特别是 Provide 和 Inject,它们的原理、用法和示例

    Vue.js 作为一款现代的前端 JavaScript 框架,提供了诸多方便开发的特性。其中依赖注入是一个非常有用的功能,可以在组件树中传递数据和方法,并使得组件之间的耦合度更低。本文将介绍 Vue 中的依赖注入,特别是 Provide 和 Inject,它们的原理、用法和示例。 在软件开发中,

    2024年02月06日
    浏览(41)
  • 展开说说provide和inject

    写在前面 今天讲一下关于vue组件传值里面的其中一个跨组件传值,之前文章写过一篇关于组件传值,里面也有提过关于这块跨组件传值的方式,其中就提到了provide 和 inject的方式,但是并没有展开说,今天就简单的展开说一下,他的取值问题 讲解思路 今天的思路是,我会写

    2024年01月23日
    浏览(42)
  • vue3中的吸顶导航交互实现 | VueUse插件

    目的:浏览器上下滚动时,若距离顶部的滚动距离大于78px,吸顶导航显示,小于78px隐藏。使 用vueuse插件中的 useScroll方法 ​​​​​​​ 和 动态类名控制 进行实现 项目中导入,解构出 useScroll方法的其他参数: 参考:useScroll | VueUse中文文档 (vueusejs.com)

    2024年02月09日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包