当前位置: 首页 > news >正文

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

什么是hooks

自定义hooks 是Vue3 组合式函数的别称。

在 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.pageXy.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.pageXy.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实例对象readerconst 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实例对象readerconst 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 方法来拒绝 Promisereject(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 的编译器会在异步操作之后自动为你恢复当前的组件实例。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • PHP语言有哪些优势和特点?
  • C——四种排序方法
  • 84、 k8s的pod基础+https-harbor
  • 行级安全的艺术:SQL中的精细化数据保护策略
  • C++中类的相关学习
  • Golang 教程2
  • NoSql数据库 Redis集群详解
  • 如何使用 Pytest 进行测试
  • 【AI绘画】Midjourney前置指令/describe、/shorten详解
  • 给自己复盘用的tjxt笔记day12第一部分
  • Android 事件分发:为什么有时候会出现事件冲突?事件的顺序是如何的?出现事件冲突如何解决呢?比如为什么左右可以滑动,而上下却不行?
  • 中信银行与中国国家地理携手致敬中国极地考察40周年
  • 查看 mysql 密码过期策略,设置永不过期
  • 医疗器械法规笔记
  • 虚幻5|按键触发学习
  • @jsonView过滤属性
  • Angular 2 DI - IoC DI - 1
  • Apache Zeppelin在Apache Trafodion上的可视化
  • Django 博客开发教程 8 - 博客文章详情页
  • E-HPC支持多队列管理和自动伸缩
  • Hexo+码云+git快速搭建免费的静态Blog
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • spring cloud gateway 源码解析(4)跨域问题处理
  • vuex 学习笔记 01
  • vue中实现单选
  • 编写符合Python风格的对象
  • 解析 Webpack中import、require、按需加载的执行过程
  • 微信小程序填坑清单
  • 无服务器化是企业 IT 架构的未来吗?
  • 消息队列系列二(IOT中消息队列的应用)
  • 硬币翻转问题,区间操作
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • #1014 : Trie树
  • (07)Hive——窗口函数详解
  • (6)设计一个TimeMap
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (TipsTricks)用客户端模板精简JavaScript代码
  • (八十八)VFL语言初步 - 实现布局
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (附源码)springboot人体健康检测微信小程序 毕业设计 012142
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (十八)Flink CEP 详解
  • (五)关系数据库标准语言SQL
  • (原创) cocos2dx使用Curl连接网络(客户端)
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .NET Core IdentityServer4实战-开篇介绍与规划
  • .NET 服务 ServiceController
  • .net 生成二级域名
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .net快速开发框架源码分享
  • .NET框架
  • .NET中两种OCR方式对比