vue3-逻辑复用

什么是组合式函数

_无状态逻辑的函数_:它在接收一些输入后立刻返回所期望的输出。

比如 时间格式化的函数。

有状态逻辑的函数: 有状态逻辑负责管理会随时间而变化的状态。

比如 跟踪当前鼠标在页面中的位置。

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

一个简单的例子是跟踪当前鼠标在页面中的位置。在实际应用中,也可能是像触摸手势或与数据库的连接状态这样的更复杂的逻辑。

<script lang="ts" setup>
import { ref, onMounted, onUnmounted } from "vue";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));
</script><template><div class="container">鼠标坐标是: {{ x }}, {{ y }}</div>
</template>

组合函数提取,进行逻辑复用封装

// mouse.js
import { ref, onMounted, onUnmounted } from 'vue'// 按照惯例,组合式函数名以“use”开头
export function useMouse() {// 被组合式函数封装和管理的状态const x = ref(0)const y = ref(0)// 组合式函数可以随时更改其状态。function update(event) {x.value = event.pageXy.value = event.pageY}// 一个组合式函数也可以挂靠在所属组件的生命周期上// 来启动和卸载副作用onMounted(() => window.addEventListener('mousemove', update))onUnmounted(() => window.removeEventListener('mousemove', update))// 通过返回值暴露所管理的状态return { x, y }
}

封装后的使用方式:

<script lang="ts" setup>
import { useMouse } from "@/components/common/mouse.js";
const { x, y } = useMouse();
</script><template><div class="container">鼠标坐标是: {{ x }}, {{ y }}</div>
</template>

可以在组合式函数中使用所有的组合式 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))
}

有了它,之前的 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 }
}

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

如果你想要在组件之间共享状态,后面回学到状态管理。

###异步状态示例

需要接收一个参数的组合式函数示例。在做异步数据请求时,我们常常需要处理不同的状态:加载中、加载成功和加载失败。

// fetch.js
import { ref, watchEffect, toValue } from 'vue'export function useFetch(url) {const data = ref(null)const error = ref(null)const fetchData = () => {// reset state before fetching..data.value = nullerror.value = nullfetch(toValue(url)).then((res) => res.json()).then((json) => (data.value = json)).catch((err) => (error.value = err))}watchEffect(() => {fetchData()})return { data, error }
}

toValue() 是一个在 3.3 版本中新增的 API。它的设计目的是将 ref 或 getter 规范化为值。如果参数是 ref,它会返回 ref 的值;如果参数是函数,它会调用函数并返回其返回值。否则,它会原样返回参数。它的工作方式类似于 unref(),但对函数有特殊处理。

注意 toValue(url) 是在 watchEffect 回调函数的内部调用的。这确保了在 toValue() 规范化期间访问的任何响应式依赖项都会被侦听器跟踪。

这个版本的 useFetch() 现在能接收静态 URL 字符串、ref 和 getter,使其更加灵活。watch effect 会立即运行,并且会跟踪 toValue(url) 期间访问的任何依赖项。如果没有跟踪到依赖项(例如 url 已经是字符串),则 effect 只会运行一次;否则,它将在跟踪到的任何依赖项更改时重新运行。

约定和最佳实践

命名

组合式函数约定用驼峰命名法命名,并以“use”作为开头。

输入参数

即便不依赖于 ref 或 getter 的响应性,组合式函数也可以接收它们作为参数。如果你正在编写一个可能被其他开发者使用的组合式函数,最好处理一下输入参数是 ref 或 getter 而非原始值的情况。可以利用 toValue() 工具函数来实现:

import { toValue } from 'vue'function useFeature(maybeRefOrGetter) {// 如果 maybeRefOrGetter 是一个 ref 或 getter,// 将返回它的规范化值。// 否则原样返回。const value = toValue(maybeRefOrGetter)
}

如果你的组合式函数在输入参数是 ref 或 getter 的情况下创建了响应式 effect,为了让它能够被正确追踪,请确保要么使用 watch() 显式地监视 ref 或 getter,要么在 watchEffect() 中调用 toValue()。

返回值

你可能已经注意到了,我们一直在组合式函数中使用 ref() 而不是 reactive()。我们推荐的约定是组合式函数始终返回一个包含多个 ref 的普通的非响应式对象,这样该对象在组件中被解构为 ref 之后仍可以保持响应性:

// x 和 y 是两个 ref
const { x, y } = useMouse()

从组合式函数返回一个响应式对象会导致在对象解构过程中丢失与组合式函数内状态的响应性连接。与之相反,ref 则可以维持这一响应性连接。

如果你更希望以对象属性的形式来使用组合式函数中返回的状态,你可以将返回的对象用 reactive() 包装一次,这样其中的 ref 会被自动解包,例如:

const mouse = reactive(useMouse())
// mouse.x 链接到了原来的 x ref
console.log(mouse.x)
使用限制

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

这些限制很重要,因为这些是 Vue 用于确定当前活跃的组件实例的上下文。访问活跃的组件实例很有必要,这样才能:

  • 将生命周期钩子注册到该组件实例上

  • 将计算属性和监听器注册到该组件实例上,以便在该组件被卸载时停止监听,避免内存泄漏。

<script setup> 是唯一在调用 await 之后仍可调用组合式函数的地方。编译器会在异步操作之后自动为你恢复当前的组件实例。

与其他模式的比较

和 Mixin 的对比

Vue 2 的用户可能会对 mixins 选项比较熟悉。它也让我们能够把组件逻辑提取到可复用的单元里。然而 mixins 有三个主要的短板:

不清晰的数据来源:当使用了多个 mixin 时,实例上的数据属性来自哪个 mixin 变得不清晰,这使追溯实现和理解组件行为变得困难。这也是我们推荐在组合式函数中使用 ref + 解构模式的理由:让属性的来源在消费组件时一目了然。

命名空间冲突:多个来自不同作者的 mixin 可能会注册相同的属性名,造成命名冲突。若使用组合式函数,你可以通过在解构变量时对变量进行重命名来避免相同的键名。

隐式的跨 mixin 交流:多个 mixin 需要依赖共享的属性名来进行相互作用,这使得它们隐性地耦合在一起。而一个组合式函数的返回值可以作为另一个组合式函数的参数被传入,像普通函数那样。

基于上述理由,我们不再推荐在 Vue 3 中继续使用 mixin。保留该功能只是为了项目迁移的需求和照顾熟悉它的用户。

和无渲染组件的对比

在组件插槽一章中,我们讨论过了基于作用域插槽的无渲染组件。我们甚至用它实现了一样的鼠标追踪器示例。

组合式函数相对于无渲染组件的主要优势是:组合式函数不会产生额外的组件实例开销。当在整个应用中使用时,由无渲染组件产生的额外组件实例会带来无法忽视的性能开销。

我们推荐在纯逻辑复用时使用组合式函数,在需要同时复用逻辑和视图布局时使用无渲染组件。

和 React Hooks 的对比

如果你有 React 的开发经验,你可能注意到组合式函数和自定义 React hooks 非常相似。组合式 API 的一部分灵感正来自于 React hooks,Vue 的组合式函数也的确在逻辑组合能力上与 React hooks 相近。然而,Vue 的组合式函数是基于 Vue 细粒度的响应性系统,这和 React hooks 的执行模型有本质上的不同。这一话题在组合式 API 的常见问题中有更细致的讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/663701.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端换肤的五种思路和优缺点

一、什么是前端换肤 前端换肤是指在前端开发中&#xff0c;通过改变网页的样式来实现不同的主题或皮肤效果。通过换肤&#xff0c;可以改变网页的颜色、字体、背景等样式&#xff0c;以适应不同的用户喜好或实现特定的设计需求。 静态换肤&#xff1a; 是指在网页加载时&…

python-自动化篇-运维-可视化-绘图库-matplotlib

文章目录 Matplotlibmatplotlib开发环境搭建绘制基础绘制直线绘制折线设置标签文字和线条粗细绘制一元二次方程的曲线yx^2绘制正弦曲线和余弦曲线散点图绘制柱状图绘制饼状图绘制直方图等高线图绘制三维图 Matplotlib Matplotlib 是一个Python的 2D绘图库。通过 Matplotlib&am…

leetcode 19 , 118

19 .删除链表倒数第n个节点 思路1&#xff1a; 我首先想到的就是使用两个loop来进行解决&#xff1a; 遍历所有节点&#xff0c;得到需要删除节点的位置。再遍历一边所有节点&#xff0c;找到需要删除节点进行删除。 解决方案1&#xff1a; class Solution {public ListNod…

代码随想录算法训练营第二十四天|● 理论基础 ● 77. 组合

仅做学习笔记&#xff0c;详细请访问代码随想录 ● 理论基础 ● 77. 组合 ● 理论基础 回溯法解决的问题 回溯法&#xff0c;一般可以解决如下几种问题&#xff1a; 组合问题&#xff1a;N个数里面按一定规则找出k个数的集合 切割问题&#xff1a;一个字符串按一定规则有几…

新增模型检验,指标自动评估模型效果|ModelWhale 版本更新

二月将至&#xff0c;ModelWhale 迎来开年首次版本更新&#xff0c;期待为大家带来更优质的使用体验。 本次更新中&#xff0c;ModelWhale 主要进行了以下功能迭代&#xff1a; 新增 模型检验&#xff08;团队版✓&#xff09;优化 模型评审测试&#xff08;团队版✓&#xf…

如何在Shopee平台上进行手机类目选品?

在Shopee平台上进行手机类目的选品是一个关键而复杂的任务。卖家需要经过一系列的策略和步骤&#xff0c;以确保选品的成功和销售业绩的提升。下面将介绍一些有效的策略&#xff0c;帮助卖家在Shopee平台上进行手机类目选品。 先给大家推荐一款shopee知虾数据运营工具知虾免费…

c#的反汇编对抗

文章目录 前记nim攻防基础FFI内存加载加解密、编码 后记C#类型转换表nim基础 前记 随便编写一个c#调用winapi并用vs生成dll,同时用csc生成exe using System; using System.Runtime.InteropServices; namespace coleak {class winfun{[DllImport("User32.dll")]publ…

【算法】约数之和(数论)

题目 给定 n 个正整数 ai&#xff0c;请你输出这些数的乘积的约数之和&#xff0c;答案对 1097 取模。 输入格式 第一行包含整数 n。 接下来 n 行&#xff0c;每行包含一个整数 ai。 输出格式 输出一个整数&#xff0c;表示所给正整数的乘积的约数之和&#xff0c;答案需…

3593 蓝桥杯 查找最大元素 简单

3593 蓝桥杯 查找最大元素 简单 // C风格解法1&#xff0c;通过率100%&#xff0c;多组数据处理样式//str "abcdefgfedcba" //abcdefg(max)fedcba//str "xxxxx" //x(max)x(max)x(max)x(max)x(max)#include<bits/stdc.h>const int N 1e2 10;char …

【每日一题】石子游戏 VI

文章目录 Tag题目来源解题思路方法一&#xff1a;贪心排序 写在最后 Tag 【贪心排序】【数组】【2024-02-02】 题目来源 1686. 石子游戏 VI 解题思路 方法一&#xff1a;贪心排序 思路 假设有两个石子 i 和 j&#xff0c;Alice 和 Bob 认为它们的价值分别为 a i a_i ai​…

Linux系统Shell脚本-----------正则表达式 文本三剑客之---------grep、 sed

一、正则表达式 1.前言 正则表达式(regular expression)描述了一种字符串匹配的模式&#xff08;pattern&#xff09;&#xff0c;可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。在Linux中也就是代表我们定义的模式模板&…

qt学习:qt项目移植多平台

目录 window linux 安装qt步骤 在linux编译可执行程序步骤 arm 要先移植交叉编译链才能在ubuntu里生成arm的qt可执行文件&#xff0c;下面是步骤 安装arm的qmake 在linux编译可执行程序步骤 进入官网下载qt&#xff0c;下载window&#xff0c;linux的安装包&#xff0c…

让Unity迭代器性能提升5倍

最近在研究Unity il2cpp的代码生成和编译优化&#xff0c;结合之前遇到过的一个优化案例&#xff0c;给大家讲讲在Unity中迭代器相关代码生成的底层原理&#xff0c;以及在写代码过程中需要注意的一些特殊情况。 案例 首先我们来看一个非常简单的案例&#xff0c;代码如下&am…

Linux实验记录:使用Apache服务部署静态网站

前言&#xff1a; 本文是一篇关于Linux系统初学者的实验记录。 参考书籍&#xff1a;《Linux就该这么学》 实验环境&#xff1a; VmwareWorkStation 17——虚拟机软件 RedHatEnterpriseLinux[RHEL]8——红帽操作系统 目录 前言&#xff1a; 备注&#xff1a; 正文&…

【C语言进阶篇】assert宏 使用详解

文章目录 一、assert简介 二、assert使用方法和规则 2.1 头文件 2.2 原型 2.3 功能 2.4 示例 2.5 assert的打开与关闭 三、注意事项 3.1 运行效率问题 3.2 assert只适用于调试版本 3.3 资源释放与清理 3.4 过度依赖 四、总结 个人主页&#xff1a; 倔强的石头的…

氢气传感器报警值:守护实验室安全的隐形卫士

随着科技的发展&#xff0c;我们的生活变得越来越便捷&#xff0c;但是与此同时&#xff0c;安全问题也日益凸显。其中&#xff0c;氢气作为一种清洁能源&#xff0c;被广泛应用于各个领域&#xff0c;但是如果不加以控制&#xff0c;氢气泄漏也可能带来严重的安全隐患。因此&a…

柔性电流探头方向判断有哪些方法?干货分享!

柔性电流探头方向判断的方法干货分享&#xff01;从理论到实践&#xff0c;助您成为专业人士&#xff01;干货收藏&#xff0c;快看起来吧&#xff01;      柔性电流探头方向判断一直是电力行业测试中的关键问题之一&#xff0c;确切地判断电流方向对于测试电力系统的稳定…

Docker部署xxl-job调度器并结合SpringBoot测试

文章目录 一、Docker部署1. 创建数据库2. 启动容器3. 访问4. 新建执行器 二、SpringBoot整合1. 模块注册到执行器2. 创建配置类3. 启动测试 三、任务发布-普通任务1. 编写任务代码2. 创建任务3. 启动任务 四、任务发布-分片任务1. 编写任务代码2. 启动多个实例3. 创建任务4. 启…

CTF特训(二):青少年CTF-MISC部分WP

FLAG&#xff1a;当觉得自己很菜的时候&#xff0c;就静下心来学习 专研方向:MISC&#xff0c;CTF 每日emo&#xff1a;听一千遍反方向的钟&#xff0c;我们能回到过去吗&#xff1f; CTF特训(二)&#xff1a;青少年CTF-MISC部分WP&#xff1a; 文章目录 CTF特训(二)&#xff1…

IDEA开发使用 thymeleaf 模板$表达式报红波浪线解决方案

系列文章目录 文章目录 系列文章目录后端存值前端取值thymeleaf 后端存值 RequestMapping("/testModelAndView")//使用ModelAndView时返回的方法类型必须是ModelAndViewpublic ModelAndView testModelAndView() {//创建ModelAndView对象ModelAndView mav new Model…