返回 导航

Vue.js

hangge.com

Vue.js 3 - Composition API使用详解10(封装Hook函数实现代码逻辑复用)

作者:hangge | 2026-05-08 08:38
    之前我演示了如何使用 Mixin 混入实现 Options API 中代码的逻辑封装和复用(点击查看),但这种方式存在来源不清晰、命名冲突风险高、逻辑耦合严重以及难以追踪数据来源等问题,在组件复杂度提升后,代码的可维护性和可读性都会明显下降。
    而在 Composition API 中,我们可以将同一个关注点的逻辑代码封装到一个函数中,该函数通常约定以 use 为前缀命名,比如 useCounter。以 use 开头的函数,我们称之为自定义 Hook 函数,它通过返回响应式数据和操作方法,将状态与行为显式暴露给使用者,逻辑来源清晰、组合方式灵活,并且天然支持数据响应式与生命周期管理。

十、通过 Hook 函数实现代码逻辑的封装和复用

1,计数器样例

(1)首先我们创建一个 useCounter.js 文件,将计数器的代码逻辑封装到一个 useCounte 函数中。
import { ref, computed } from "vue";

export default function useCounter() {
  const counter = ref(100);
  const doubleCounter = computed(() => counter.value * 2);

  const increment = () => counter.value++;
  const decrement = () => counter.value--;

  return {
    counter,
    doubleCounter,
    increment,
    decrement,
  };
}

(2)然后我们的组件中就可以导入 useCounter 自定义 Hook 函数,并在 setup 中调用该函数,这样便可以获取到返回的响应式数据和事件函数,并返回给模板使用。
<template>
    <div>
        <div>当前计数: {{ counter }}</div>
        <div>当前计数*2: {{ doubleCounter }}</div>
        <button @click="increment">+1</button>
        <button @click="decrement">-1</button>
    </div>
</template>

<script>
import useCounter from './useCounter'
export default {
    setup() {
        // 计数器的代码逻辑抽取到useCounter hook 中了
        const { counter, doubleCounter, increment, decrement } = useCounter()
        return { counter, doubleCounter, increment, decrement }
    }
}
</script>

(3)运行效果如下图所示:

2,修改网页标题样例

(1)首先我们创建一个 useTitle.js 文件,将修改网页标题的代码逻辑封装到一个匿名函数中。
import { ref, watch } from 'vue';
// 使用匿名函数,并该函数需接收一个参数
export default function(title = "默认的title") {
  const titleRef = ref(title);
  // 侦听titleRef变化,一旦被修改就更新 
  watch(titleRef, (newValue) => {
    document.title = newValue 
  }, {
    immediate: true // 侦听的回调函数先执行一次
  })
  return titleRef
}

(2)然后在我们的组件中导入自定义 Hook 函数 useTitle,然后在 setup 函数中调用 useTitle 函数, 将页面标题初始化为“航歌”。之后,经过 3 秒钟的等待,页面标题就会被改为 hangge.com
<template>
    <div>
    </div>
</template>

<script>
import useTitle from './useTitle'

export default {
    setup() {
        // 修改网页的标题
        const titleRef = useTitle("航歌");
        setTimeout(() => {
            // 3秒后将标题由航歌改为hangge.com
            titleRef.value = "hanggge.com"
        }, 3000);
        return {}
    }
}
</script>

(3)在浏览器中可看到页面标题在 3 秒后由“航歌”变为“hanggge.com”。

3,监听页面滚动位置样例

(1)首先我们创建一个 useScrollPosition.js 文件,将监听页面滚动位置的代码逻辑封装到一个 useScrollPosition 函数中。
import { ref } from 'vue';
// 自定义 useScrollPosition Hook函数
export default function useScrollPosition() {
  const scrollX = ref(0);
  const scrollY = ref(0);

  document.addEventListener("scroll", () => {
    scrollX.value = window.scrollX;
    scrollY.value = window.scrollY;
  });

  return {scrollX, scrollY} // 返回响应式数据
}

(2)导入 useScrollPosition 函数,接着在 setup 中调用 useScrollPosition 函数, 获取到当前滚动的值。如果滚动页面了,那么 useScrollPosition 函数会监听到并修改 scrolIXscrollY 响应式变量的值,同时更新页面。
<template>
    <div>
        <!-- 显示页面滚动位置 -->
        <p style="width: 3000px;height: 5000px;">
            width:3000px height:5000px的,模拟页面滚动
        </p>
        <div style="position: fixed;top:20px;right:20px">
            <div class="scroll-x">scrollX: {{ scrollX }}</div>
            <div class="scroll-y">scrollY: {{ scrollY }}</div>
        </div>

    </div>
</template>

<script>
import useScrollPosition from './useScrollPosition'
export default {
    setup() {
        // 监听页面滚动位置
        const { scrollX, scrollY } = useScrollPosition();
        return { scrollX, scrollY }
    }
}
</script>

(3)浏览器中滚动网页时,页面右上角的 scrollXscrollY 能显示当前滚动的位置。
评论

全部评论(0)

回到顶部