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

vue-23(创建用于逻辑提取的可重用组合组件)

创建用于逻辑提取的可重用组合组件

可重用的组合式是 Vue 组合式 API 的基石,它使你能够在多个组件中提取和重用有状态逻辑。这有助于编写更清晰的代码,减少冗余,并提高可维护性。通过将特定功能封装到组合式中,你可以轻松地共享和管理复杂的逻辑,使你的 Vue 应用更具可扩展性和组织性。本课程将深入探讨创建有效且可重用组合式的原则和技术。

理解组合式

从本质上讲,组合式是一个封装并返回可在多个组件中使用的有状态逻辑的函数。它利用组合式 API 的特性,如 refreactive 和生命周期钩子来管理状态和副作用。主要目标是将从组件中提取的复杂逻辑转化为可重用的单元,从而推广 DRY(不要重复自己)原则。

可重用的原则

要创建真正可重用的组合组件,请考虑这些原则:

  • 单一职责原则: 每个可组合项应专注于一个特定且明确定义的任务。避免创建处理多个不相关功能的"上帝"可组合项。
  • 配置选项: 允许组件通过选项或参数来配置可组合组件的行为。这使得可组合组件更能适应不同的使用场景。
  • 清晰的 API: 为可组合组件定义一个清晰简洁的 API,使其他开发者易于理解和使用。
  • 可测试性: 确保该组合件能够独立于其他部分轻松进行测试。这有助于保持其质量并防止回归问题。
  • 解耦: Composables 应与特定组件或应用逻辑解耦。它们应设计得尽可能通用。

基本示例:useMouse

让我们从一个简单的例子开始:一个跟踪鼠标位置的组合式组件。

// composables/useMouse.js
import { ref, onMounted, onUnmounted } from 'vue';export function useMouse() {const x = ref(0);const y = ref(0);function update(event) {x.value = event.pageX;y.value = event.pageY;}onMounted(() => {window.addEventListener('mousemove', update);});onUnmounted(() => {window.removeEventListener('mousemove', update);});return { x, y };
}

解释:

  • ref: 为 x 和 y 坐标创建响应式引用。
  • update: 一个根据鼠标事件更新 x 和 y 坐标的函数。
  • onMounted: 组件挂载时注册 mousemove 事件监听器。
  • onUnmounted: 组件卸载时移除事件监听器以防止内存泄漏。
  • return: 返回一个包含响应式 x 和 y 坐标的对象,可在组件模板中使用。

在组件中使用:

<template><p>Mouse position: x={{ x }}, y={{ y }}</p>
</template><script>
import { useMouse } from '../composables/useMouse';export default {setup() {const { x, y } = useMouse();return { x, y };}
};
</script>

高级组合式:逻辑提取

现在,让我们探索更复杂的场景,其中可组合组件可以显著提高代码的组织性和可重用性。

示例:useFetch

在 Web 应用程序中,从 API 获取数据是一项常见任务。让我们创建一个 useFetch 可组合组件来处理这个任务。

// composables/useFetch.js
import { ref, reactive, toRefs } from 'vue';export function useFetch(url) {const data = ref(null);const error = ref(null);const loading = ref(false);const state = reactive({data,error,loading})const fetchData = async () => {loading.value = true;try {const response = await fetch(url);if (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);}data.value = await response.json();} catch (err) {error.value = err;} finally {loading.value = false;}};fetchData(); // Immediately fetch data when the composable is usedreturn {...toRefs(state),fetchData // Expose the fetchData function to allow manual re-fetching};
}

解释:

  • 数据 ,  错误 ,  加载中 :用于存储获取的数据、发生的任何错误以及加载状态的响应式引用。
  • fetchData: 一个异步函数,从给定 URL 获取数据,处理错误,并更新响应式引用。
  • toRefs: 将响应式对象 state 转换为 ref 对象,允许在组件中进行解构。
  • 当可组合函数被使用时,fetchData 函数会立即被调用,启动数据获取过程。
  • fetchData 函数也会被返回,允许组件在需要时手动触发重新获取数据。

在组件中使用:

<template><div v-if="loading">Loading...</div><div v-else-if="error">{{ error.message }}</div><div v-else><h1>{{ data.title }}</h1><p>{{ data.body }}</p><button @click="fetchData">Refresh</button></div>
</template><script>
import { useFetch } from '../composables/useFetch';export default {setup() {const { data, error, loading, fetchData } = useFetch('https://jsonplaceholder.typicode.com/posts/1');return { data, error, loading, fetchData };}
};
</script>

示例:useLocalStorage

另一个常见需求是在本地存储中持久化数据。让我们创建一个 useLocalStorage 组合式。

// composables/useLocalStorage.js
import { ref, watch, onMounted } from 'vue';export function useLocalStorage(key, defaultValue = null) {const storedValue = ref(defaultValue);onMounted(() => {// Initialize from localStorage on mountconst item = localStorage.getItem(key);if (item) {try {storedValue.value = JSON.parse(item);} catch (error) {console.error("Error parsing stored value:", error);// If parsing fails, leave it as default or handle as needed}}});watch(storedValue,(newValue) => {localStorage.setItem(key, JSON.stringify(newValue));},{ deep: true } // Watch for changes in nested objects/arrays);return storedValue;
}

解释:

  • storedValue: 一个反应式引用,用于存储本地存储中的值。
  • onMounted: 在组件挂载时从本地存储中获取值,并初始化 storedValue
  • watch: 监听 storedValue 的变化并相应地更新本地存储。deep: true 选项确保可以检测到嵌套对象或数组的更改。
  • 包含错误处理,以便在存储的值不是有效 JSON 的情况下优雅地处理。

在组件中使用:

<template><div><input v-model="name" placeholder="Enter your name"><p>Hello, {{ name }}!</p></div>
</template><script>
import { useLocalStorage } from '../composables/useLocalStorage';export default {setup() {const name = useLocalStorage('name', '');return { name };}
};
</script>

处理配置选项

为了让可组合项更加灵活,你可以将配置选项作为参数传递。例如,让我们修改 useFetch 可组合项,使其接受一个选项对象。

// composables/useFetch.js
import { ref, reactive, toRefs } from 'vue';export function useFetch(url, options = {}) {const data = ref(null);const error = ref(null);const loading = ref(false);const state = reactive({data,error,loading})const fetchData = async () => {loading.value = true;try {const response = await fetch(url, options); // Pass options to fetchif (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);}data.value = await response.json();} catch (err) {error.value = err;} finally {loading.value = false;}};fetchData();return {...toRefs(state),fetchData};
}

在组件中使用:

<template><div v-if="loading">Loading...</div><div v-else-if="error">{{ error.message }}</div><div v-else><h1>{{ data.title }}</h1><p>{{ data.body }}</p></div>
</template><script>
import { useFetch } from '../composables/useFetch';export default {setup() {const options = {headers: {'Authorization': 'Bearer my-token'}};const { data, error, loading } = useFetch('https://jsonplaceholder.typicode.com/posts/1', options);return { data, error, loading };}
};
</script>

在这个示例中,useFetch 组合函数现在接受一个直接传递给 fetch 函数的 options 对象,允许你配置请求头、方法和其他请求参数。

相关文章:

  • 一键内网穿透,无需域名和服务器,自动https访问
  • 通信网络编程3.0——JAVA
  • Polar (极化)码的译码Ⅲ--级联 Polar 码
  • 在Ubuntu上设置Selenium自动化测试环境:Chrome与Firefox的详细指南
  • Flutter ListTile 徽章宽度自适应的真正原因与最佳实践
  • 速通Ceph分布式存储(含超详细图解)
  • 【ARM 嵌入式 编译系列 7.5 -- GCC 打印链接脚本各段使用信息】
  • minidocx: 一个轻量级的跨平台的C++操作word的开源库
  • 黑马React001
  • 本地部署MoneyPrinterTurbo并配置远程访问实战
  • 为WordPress 网站创建一个纯文本网站地图(Sitemap)
  • 【RK3568 嵌入式linux QT开发笔记】 二维码开源库 libqrencode 交叉静态编译和使用
  • vue-22(理解组合式 API:setup、ref、reactive)
  • 3.2.1小节 扣子平台给智能体绑定插件
  • DeepSeek中的提示库及其用法示例
  • OSC靶机练习 PG ZenPhoto
  • Spring Boot + Logback MDC 深度解析:实现全链路日志追踪
  • [论文阅读] 人工智能 + 软件工程 | AI 驱动工具在软件质量保证中的革新:挑战与未来之路
  • Spring AI 项目实战(十二):Spring Boot +AI + DeepSeek + 百度OCR 公司发票智能处理系统的技术实践(附完整源码)
  • 爬虫中网络知识基础
  • wap网站搭建/sem是什么基团
  • 网页设计源代码css案例/网络营销的优化和推广方式
  • 导视设计网站/公司怎么做网站推广
  • ps 做儿童摄影网站首页/经典软文案例和扶贫农产品软文
  • 浙0577 icp网站建设/免费广告推广
  • 做品牌特价的网站有哪些/体育热点新闻