当前位置: 首页 > 知识库问答 >
问题:

vue3 如何更好的写hooks函数?

冀鸿才
2024-07-30

关于vue3如何写hooks的问题?

export function useChangeTableHeaderWidth(list) {
  const time = Date.now()
  const getWidthClass = `getWidth${time}`
  const setWidthClass = `setWith${time}`
  function resizeStep(setWidthElement: HTMLElement) {
    const fontSize = window.getComputedStyle(setWidthElement).fontSize
    let size = parseInt(fontSize)
    const scrollwidth = setWidthElement.scrollWidth
    const clientWidth = setWidthElement.clientWidth
    if (scrollwidth > clientWidth && size > 0) {
      size -= 1
      setWidthElement.style.fontSize = size + 'px'
      requestAnimationFrame(() => {
        resizeStep(setWidthElement)
      })
    }
  }
  watch(
    list,
    () => {
      const getWidth = document.getElementsByClassName(getWidthClass)
      const setWidth = document.getElementsByClassName(setWidthClass)
      for (const index in getWidth) {
        if (Object.prototype.hasOwnProperty.call(setWidth, index)) {
          /* 获取td的宽度,设置给th */
          const getWidthElement = getWidth[index]
          const width = getWidthElement.clientWidth
          const setWidthElement = setWidth[index] as HTMLElement
          // 这样写要去eslintrc文件里关闭对jsx的语法检查
          // let setWidthElement = <HTMLElement>setWidth[index]
          setWidthElement.style.width = width + 'px'

          /* title字体大于宽度的时,让字体变小 */
          const scrollwidth = setWidthElement.scrollWidth
          const clientWidth = setWidthElement.clientWidth
          if (scrollwidth > clientWidth) {
            resizeStep(setWidthElement)
          }
        }
      }
    },
    {
      flush: 'post',
    },
  )

  return [getWidthClass, setWidthClass]
}

如何限值list是ref值,亦或者即使传入的是普通值,也可以触发watch?还有就是这个hooks中的watch在使用了hooks之后一直存在吗,还是说组件销毁了watch就自动销毁,还是需要在这个hooks在写上组件卸载时手动销毁。

我记得antfu之前有个演讲提到过在hooks里用geter函数和tovalue、toref来提升兼容性,但是我记不清了,不知道能不能使用在这里,还有个effectScope我记得写hooks的时候好像也挺有用。

共有1个答案

戚浩淼
2024-07-30

在Vue 3中编写hooks函数时,确保它们既灵活又高效是很重要的。针对你提到的问题,我会逐一解答并提供改进建议。

如何限制list是ref值或处理普通值

Vue 3的watch函数默认期望监视的是一个响应式引用(如refreactive对象)。如果你希望watch能够处理普通值(即非响应式值),你需要将这些值包装成响应式引用。这可以通过ref函数来实现。然而,如果list已经是响应式的,直接传入即可。

你可以修改你的hook来自动处理这个问题:

import { ref, watch, EffectScope } from 'vue';

export function useChangeTableHeaderWidth(list: any) {
  // 如果list不是ref,则包装成ref
  const listRef = ref(list);

  // 后续逻辑保持不变,但使用listRef.value代替list
  // ...

  watch(
    () => listRef.value,
    // ...
  );

  // 返回时可以考虑是否公开listRef.value的更新能力
  // 这里仅作为示例,实际根据需求调整
  return [getWidthClass, setWidthClass];
}

watch的销毁

在Vue 3中,watch函数自动与组件的生命周期绑定。这意味着当组件被销毁时,由该组件创建的watch也会自动停止。因此,你不需要(也不应该)在hooks中手动销毁watch

getter函数和toRef/toRefs

虽然Antfu的演讲可能提到了使用getter函数和toRef/toRefs来提升兼容性或优化,但这些通常用于当你需要从响应式对象中提取某些属性并希望保持这些属性的响应性时。在你的场景中,如果你需要保持list的某个属性的响应性,并且这个属性是reactive对象的一部分,那么toReftoRefs可能会很有用。但在你的例子中,由于你可能是在处理整个列表的响应性,直接使用ref或确保传入的是响应式对象就足够了。

EffectScope

EffectScope是Vue 3中引入的一个API,它允许你创建一个新的响应性作用域。这在你需要隔离或管理一组副作用(如watchers、computed等)时非常有用。然而,在你的例子中,如果没有特别的需求去隔离或控制这些副作用的作用域,你可能不需要直接使用EffectScope

总结

  • 使用ref来确保传入watch的值是响应式的。
  • watch会自动与组件的生命周期绑定,无需手动销毁。
  • 根据你的具体需求考虑是否使用toRef/toRefsEffectScope

希望这些解答能帮助你更好地理解和使用Vue 3中的hooks函数!

 类似资料:
  • 第一种方式: App.vue NavTree.vue 第二种方式: App.vue NavTree.vue 上面这两个种 ids 和 nav_ids 传值, 哪种传值会更快,还是说都一样,如果 navs 很多的时候

  • 这就是它看起来的样子。 它工作得很好,等待数据加载,然后开始操作。但这是相当多的代码,有没有更好的方法来做它?

  • vue3 如何 使用 vue2.7写的代码?以前的项目都是vue2写的,版本被我升级成了vue2.7,最近开了一个新项目,我使用了vue3,需要用到vue2写好的几个组件,我现在没时间把代码改成vue3组合式写法了,然后我想着vue3不是也支持选项式写法吗,我就直接把vue2的组件copy过来,volar倒是没有报语法错误,但是项目跑不起来。报错截图。 vue3的选项式写法难道和vue2的写法有什

  • 我有一小段代码。我想用更好的方式写它,用更少的嵌套支票。我怎样才能实现呢? 有没有什么简洁的方法可以让我用Java 8重写上面的代码呢?

  • 我正在研究一个c项目,我有一个如下案例: 如你所见,我有两个重载函数。< br >它们的逻辑结构相同,但有些细节不同。< br > 我在考虑是否有一些技术可以将它们合并,这样我就可以有一个更好的设计。因为现在如果我需要做一些改变,我必须改变两次。

  • null field name=“path_exact”type=“string”indexed=“true”stored=“true”termvectors=“true”/> field name=“title”type=“text_general”indexed=“true”stored=“true”multivalued=“true”termvectors=“true”/> 提到的唯一键 使