首页 > 其他分享 >vue3 自定义hooks(组合式函数)

vue3 自定义hooks(组合式函数)

时间:2024-08-27 22:24:02浏览次数:15  
标签:组合式 const 函数 自定义 hooks vue3 ref event

什么是hooks

自定义hooksVue3 组合式函数的别称。

在 Vue 应用的概念中,“组合式函数”(Composables) 是一个利用 Vue 的组合式 API 来封装和复用有状态逻辑的函数。

  • 命名规范
    • 组合式函数约定用驼峰命名法命名,并以“use”作为开头。以便识别它们是可复用的逻辑单元。
    • 例如,useCounteruseFetchData等。
  • 函数结构
    • 组合式函数可以接收一些参数,这些参数可以是初始值、配置选项等。
    • 函数内部可以使用 Vue 的响应式 API(如refreactive等)来创建响应式数据,并定义一些方法来操作这些数据。
    • 最后,函数返回一个包含响应式数据和方法的对象。
  • 返回值
    • Vue官方推荐组合式函数始终返回一个包含多个 ref 的普通的非响应式对象,该对象在组件中被解构为 ref 之后仍可以保持响应性:
      当组合式函数返回一个包含多个 ref 的对象时,在组件中解构这个对象后,每个解构出来的 ref 仍然保持响应性。这意味着如果 ref 的值发生变化,组件会自动重新渲染以反映这个变化。
    • 可以使用reactive()包装返回的对象:
const mouse = reactive(useMouse())
// mouse.x 链接到了原来的 x ref
console.log(mouse.x)
  • 使用方式
    • 在 Vue 组件中,使用import语句导入 hooks ,并像调用普通函数一样调用它们。
      例如:import { useMouse } from '@/hooks/mouse.js';
    • 在使用时,显式的将响应式变量或者方法解构暴露出来
      例如:const { x, y } = useMouse()

使用

一个简单的加减功能

useCounter.ts

import { ref } from 'vue';
// 按照惯例,组合式函数名以“use”开头
export function useCounter(initialValue = 0) {
  const count = ref(initialValue);

  const increment = () => {
    count.value++;
  };

  const decrement = () => {
    count.value--;
  };
  
   // 通过返回值暴露响应式变量、方法
  return {
    count,
    increment,
    decrement,
  };
}

.vue中使用:

<template>
  <div>
    <div>Count: {{ count }}</div>
    <button @click="increment">Increment</button>
    <button @click="decrement">Decrement</button>
  </div>
</template>
<script setup lang="ts" >
import { useCounter } from '@/hooks/useCounter.ts';
const { count, increment, decrement } = useCounter();
</script>

鼠标跟踪功能

把功能实现封装到mouse.ts中:

// mouse.ts
import { onMounted, onUnmounted, ref } from 'vue'

// 按照惯例,组合式函数名以“use”开头
export function useMouse() {
  // 被组合式函数封装和管理的状态
  const x = ref(0)
  const y = ref(0)

  // 组合式函数可以随时更改其状态。
  function update(event:any) {
    x.value = event.pageX
    y.value = event.pageY
  }

  // 一个组合式函数也可以挂靠在所属组件的生命周期上
  // 来启动和卸载副作用
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  // 通过返回值暴露所管理的状态
  return { x, y }
}

.vue中使用:

<template>Mouse position is at: {{ x }}, {{ y }}</template>
<script setup lang="ts">
import { useMouse } from '@/hooks/mouse.js'

const { x, y } = useMouse()
</script>

每一个调用 useMouse() 的组件实例会创建其独有的 xy 状态拷贝,因此他们不会互相影响。

一个组合式函数可以调用一个或多个其他的组合式函数。可以像使用多个组件组合成整个应用一样,用多个较小且逻辑独立的单元来组合形成复杂的逻辑。这是组合式 API的本质。

封装 添加和清除 DOM 事件监听器

// event.js
import { onMounted, onUnmounted } from 'vue'

export function useEventListener(target, event, callback) {
  // 如果你想的话,
  // 也可以用字符串形式的 CSS 选择器来寻找目标 DOM 元素
  onMounted(() => target.addEventListener(event, callback))
  onUnmounted(() => target.removeEventListener(event, callback))
}

有了event.js,之前的 useMouse() 组合式函数可以被简化为:

// mouse.js
import { ref } from 'vue'
import { useEventListener } from './event'

export function useMouse() {
  const x = ref(0)
  const y = ref(0)

  useEventListener(window, 'mousemove', (event) => {
    x.value = event.pageX
    y.value = event.pageY
  })

  return { x, y }
}

将本地图片转化为base64格式

import { ref } from 'vue';
export default function useImageToBase64() {
  const base64Image = ref<string | null>('');

  const convertImageToBase64 = async (imageFile:File) => {
    if (imageFile) {
      // 创建FileReader实例对象reader
      const reader = new FileReader();
      // 开始读取图片文件,将其转换为 data URL(一种 base64 编码的字符串表示形式)
      reader.readAsDataURL(imageFile);
      reader.onload = (event) => {
        base64Image.value = event.target?.result as string;
      };
    } else {
      base64Image.value = null;
    }
  };

  return {
    base64Image,
    convertImageToBase64,
  };
}

在这个示例中,自定义 Hook useImageToBase64提供了一个方法convertImageToBase64来将本地图片文件转换为 base64 格式,并将结果存储在base64Image响应式变量中。在组件中,可以通过文件输入的变化事件调用这个方法,并在模板中显示转换后的图片。

<template>
  <div style="font-size: 24px;text-align: center;">首页</div>

  <div>将本地图片转换为 base64 格式的自定义 Hook 的示例:</div>
  <input type="file" @change="handleFileInputChange" />
  <img v-if="base64Image" :src="base64Image" />
</template>
<script setup>
import useImageToBase64 from '@/hooks/useImageToBase64';
const { base64Image, convertImageToBase64 } = useImageToBase64();

const handleFileInputChange = (event) => {
  const file = event.target.files[0];
  convertImageToBase64(file);
};
</script>

异步示例

// useImageToBase64.ts
export default function useImageToBase64() {
  const convertImageToBase64 = async (imageFile: File): Promise<string> => {
    return new Promise<string>((resolve, reject) => {
      // imageFile 图片文件
      if (imageFile) {
        // 创建FileReader实例对象reader
        const reader = new FileReader();
        // 开始读取图片文件,将其转换为 data URL(一种 base64 编码的字符串表示形式)
        reader.readAsDataURL(imageFile);
        // 当图片加载完成时触发load事件
        reader.onload = (event) => {
          resolve(event.target?.result as string);
        };
        reader.onerror = (error) => {
          reject(error)
        }
      } else {
        // 调用 reject 方法来拒绝 Promise
        reject(new Error('没有 File'));
      }
    })

  };

  return {
    convertImageToBase64,
  };
}

这个自定义钩子函数 useImageToBase64 的主要功能是将传入的 File 类型的图片文件转换为 base64 编码的字符串。它使用了 FileReader 对象来异步读取图片文件,并在读取成功时将结果以 Promise 的方式返回。

<template>
  <div>将本地图片转换为 base64 格式的自定义 Hook 的示例:</div>
  <input type="file" @change="handleFileInputChange" />
  <img v-if="base64Image" :src="base64Image" />
</template>
<script setup lang="ts">
import useImageToBase64 from '@/hooks/useImageToBase64';
import { ref } from 'vue';

const { convertImageToBase64 } = useImageToBase64();
let base64Image = ref('')
const handleFileInputChange = async (event) => {
  const file = event.target.files[0];
  console.log(file)
  try {
    base64Image.value = await convertImageToBase64(file);
    console.log(base64Image.value)
  }catch(err) {
    console.log(err)
  }
  
};
</script>

在选项式 API 中使用hooks

在选项式 API 中使用 hooks,hooks 必须在 setup() 中调用,且其返回的绑定必须在 setup() 中返回,以便暴露给 this 及其模板:

import { useMouse } from '@/hooks/mouse.js'
import { useFetch } from '@/hooks/fetch.js'

export default {
  setup() {
    const { x, y } = useMouse()
    const { data, error } = useFetch('...')
    return { x, y, data, error }
  },
  mounted() {
    // setup() 暴露的属性可以在通过 `this` 访问到
    console.log(this.x)
  }
  // ...其他选项
}

Vue hooks库

  • VueUse :一个基于 Vue 3 Composition API 的高质量 Hooks 库。
    • 安装:npm i @vueuse/core

hooks优点

  • hooks 作为独立逻辑的组件封装,其内部的属性、函数等和外部组件具有响应式依附的作用。
    • hooks 内部可以使用 Vue 3 的响应式 API(如 refreactive 等)来创建响应式数据。当这些 hooks 被外部组件调用时,它们返回的响应式数据可以在组件中直接使用,并且与外部组件的响应式系统相连接。
    • Vue 的响应式系统会自动收集对响应式数据的依赖关系。当 hooks 内部的响应式数据发生变化时,所有依赖于这些数据的组件都会自动触发更新。
  • hooks 可以与 Vue 3 的组合式 API 无缝结合,高内聚低耦合。
  • hooks 是独立的函数,可以更容易地对其进行单元测试。

使用限制

组合式函数只能在 <script setup>setup() 钩子中被调用。在这些上下文中,它们也只能被同步调用。在某些情况下,你也可以在像 onMounted() 这样的生命周期钩子中调用它们。

  • 组合式函数主要设计为在 <script setup>setup() 钩子中被调用。这是因为在这些上下文中,Vue 能够明确地确定当前正在设置的组件实例。
  • 在这些位置调用组合式函数可以确保正确地与组件的生命周期和响应式系统集成。例如,可以在这些地方访问组件的响应式数据和方法,并将计算属性和监听器注册到组件实例上。
  • 在某些情况下,可以在像 onMounted() 这样的生命周期钩子中调用组合式函数。这通常是在需要在特定的生命周期阶段执行一些逻辑时使用。
  • 需要注意的是,在生命周期钩子中调用组合式函数也应该遵循同步调用的原则,除非是在 <script setup> 中使用 await 之后的特殊情况。
  • 组合式函数只能被同步调用是为了确保代码的执行顺序是可预测的。如果允许异步调用组合式函数,可能会导致难以理解的代码执行顺序和潜在的错误。
  • <script setup> 中是唯一可以在调用 await 之后仍可调用组合式函数的地方。这是因为 Vue 的编译器会在异步操作之后自动为你恢复当前的组件实例。

标签:组合式,const,函数,自定义,hooks,vue3,ref,event
From: https://blog.csdn.net/fishmemory7sec/article/details/141517766

相关文章

  • MalusAdmin--- .NET 和 Vue3 实现的开源权限管理系统
    前言今天推荐一款用.NET和Vue3实现的开源权限管理系统。它的界面清爽干净,功能强大,还具备灵活的角色权限分配功能,能够满足不同规模企业的管理需求。无论你是开发新手还是大神,都能轻松上手,快速搭建起自己的权限管理体系。别再犹豫了,赶快来试试吧!项目简介Malus是海棠的意思,顾......
  • Vue3的学习---10
    10.Vuex10.1Vuex简介10.1.1Vuex概述Vuex是Vue.js应用程序的状态管理模式+库。它作为中央存储库,用于管理应用程序中所有组件的状态,并以可预测的方式进行状态变更。Vuex的设计理念是基于Flux架构,主要由以下几个核心概念组成:State(状态):存储应用程序的所有状态数据。......
  • 使用 Tampermonkey5.1.1_0加自定义编写的js脚本实现自动填充表单
    最近有碰到要使用单点登录的需求,最开始是按照固定流程使用OAuth2.0或者jwt等技术通过父子系统交互的方式实现单点登录。缺点:代码繁琐,而且需要子系统配合提供单点登录接口,并且跳转时子系统需要携带其token等参数优点:安全,通过系统交互的方式鉴权访问接口。由于要集成的子系统很多,而......
  • 基于Java Vue3学生宿舍管理系统
    一、作品包含源码+数据库+设计文档万字+全套环境和工具资源+部署教程二、项目技术前端技术:Html、Css、Js、Vue3、Element-ui数据库:MySQL后端技术:Java、SpringBoot、MyBatis三、运行环境开发工具:IDEA/eclipse数据库:MySQL8.0数据库管理工具:Navicat10以上版本环境配置......
  • 基于Java Vue3学生宿舍管理系统
    一、作品包含源码+数据库+设计文档万字+全套环境和工具资源+部署教程二、项目技术前端技术:Html、Css、Js、Vue3、Element-ui数据库:MySQL后端技术:Java、SpringBoot、MyBatis三、运行环境开发工具:IDEA/eclipse数据库:MySQL8.0数据库管理工具:Navicat10以上版本环境配置......
  • Vue3的学习---9
    9.Vue-cli脚手架9.1搭建Vue-Cli脚手架Vue-cli是一个官方提供的脚手架工具,用于快速搭建Vue.js项目。它集成了项目初始化、开发服务器、构建工具、代码检查等功能,使得开发者可以更高效地进行Vue.js应用的开发。Vue-cli官网:https://cli.vuejs.org/zh/VueCLI的主要功能包括:项......
  • quill-editor 富文本 组件封装并实现自定义上传图片
    基于quill-editor封装一个富文本组件,并实现自定义上传图片以及视频1.下载quill-editor npminstallvue-quill-editor--save2.对插件进行自定义改造(自定义字体大小选择,自定义标题,以及自定义工具栏功能) <template><divclass="edtior-box"><quill-editor......
  • Vue3项目启动失败的解决方案
    看了我创建Vue3项目的朋友们,你们是否也会出现以下情况呢,没事,我下面提供解决方案下载|Node.js中文网先把node版本安装到最新在vscode打开终端后输入yarn-s等安装好后输入yarndev启动项目即可项目启动成功了......
  • Vant4+Vue3 实现年月日时分时间范围控件
    <van-popup v-model:show="showDatePick" position="bottom" :overlay-style="{zIndex:1000}"> <van-picker-group title="时间范围" :tabs="['开始日期','结束日期']" @confirm="on......
  • WPF 自定义路由事件的实现
    路由事件通过EventManager,RegisterRoutedEvent方法注册,通过AddHandler和RemoveHandler来关联和解除关联的事件处理函数;通过RaiseEvent方法来触发事件;通过传统的CLR事件来封装后供用户使用。如何实现自定义路由事件,可以参考MSDN官网上的文档:如何:创建自定义路由事件下面的这个......