Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >12 种 Vue 设计模式

12 种 Vue 设计模式

作者头像
winty
发布于 2024-07-08 04:37:15
发布于 2024-07-08 04:37:15
31000
代码可运行
举报
文章被收录于专栏:前端Q前端Q
运行总次数:0
代码可运行

1. 数据存储模式

对于很多状态管理问题来说,最简单的解决方案是使用可组合函数来创建一个可共享的数据存储

这种模式包含几个部分:

  1. 全局状态单例
  2. 导出部分或全部状态
  3. 用于访问和修改状态的方法

下面是一个简单的例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script setup lang="ts">
import { reactive, toRefs, readonly } from 'vue';

import { themes } from './utils';

// 1. 在模块作用域中创建全局状态,在每次使用此可组合函数时共享

const state = reactive({
  darkMode: false,
  sidebarCollapsed: false,

  // 2. 此主题值对该可组合函数保持私有

  theme: 'nord',
});

export default () => {

  // 2. 仅暴露部分状态
  // 使用 toRefs 允许我们共享单个值
  const { darkMode, sidebarCollapsed } = toRefs(state);

  // 3. 修改我们的基础状态
  const changeTheme = (newTheme) => {
    if (themes.includes(newTheme)) {
      // 仅在它是一个有效主题时更新
      state.theme = newTheme;
    }
  };

  return {

    // 2. 只返回部分状态
    darkMode,
    sidebarCollapsed,

    // 2. 仅暴露状态的只读版本
    theme: readonly(state.theme),

    // 3. 我们返回一个修改基础状态的方法
    changeTheme,
  };
};
</script>

2. 轻量级可组合函数

轻量级可组合函数引入了额外的抽象层,将反应式管理与核心业务逻辑分离。这里我们使用纯 JavaScript 或 TypeScript 来实现业务逻辑,以纯函数的形式表示,并在其上添加了一层轻量级的反应式。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script setup lang="ts">
import { ref, watch } from 'vue';
import { convertToFahrenheit } from './temperatureConversion';

export function useTemperatureConverter(celsiusRef: Ref<number>) {
  const fahrenheit = ref(0);

  watch(celsiusRef, (newCelsius) => {
    // 实际逻辑包含在一个纯函数中
    fahrenheit.value = convertToFahrenheit(newCelsius);
  });

  return { fahrenheit };
}
</script>

3. 谦逊组件模式

谦逊组件的设计理念是简单,专注于展示和用户输入,将业务逻辑放在其他地方。

遵循“属性向下,事件向上”的原则,这些组件确保数据流清晰、可预测,使其易于重用、测试和维护。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <div class="max-w-sm rounded overflow-hidden shadow-lg">
    <img class="w-full" :src="userData.image" alt="User Image" />
    <div class="px-6 py-4">
      <div class="font-bold text-xl mb-2">
        {{ userData.name }}
      </div>
      <p class="text-gray-700 text-base">
        {{ userData.bio }}
      </p>
    </div>
    <div class="px-6 pt-4 pb-2">
      <button
        @click="emitEditProfile"
        class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
      >
        Edit Profile
      </button>
    </div>
  </div>
</template>

<script setup>
defineProps({
  userData: Object,
});

const emitEditProfile = () => {
  emit('edit-profile');
};
</script>

4. 提取条件逻辑

为了简化包含多个条件分支的模板,我们将每个分支的内容提取到单独的组件中。这可以提高代码的可读性和可维护性。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- 之前 -->

<template>
  <div v-if="condition">
    <!-- 真实条件下的大量代码 -->
  </div>
  <div v-else>
    <!-- 假设条件下的大量代码 -->
  </div>
</template>

<!-- 之后 -->

<template>
  <TrueConditionComponent v-if="condition" />
  <FalseConditionComponent v-else />
</template>

5. 提取可组合函数

将逻辑提取到可组合函数中,即使是单次使用的场景也是如此。可组合函数可以简化组件,使其更容易理解和维护。

它们还有助于添加相关方法和状态,例如撤销和重做功能。这有助于我们将逻辑与 UI 分开。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script setup lang="ts">
import { ref, watch } from 'vue';

export function useExampleLogic(initialValue: number) {
  const count = ref(initialValue);

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

  const decrement = () => {
    count.value--;
  };

  watch(count, (newValue, oldValue) => {
    console.log(`Count changed from ${oldValue} to ${newValue}`);
  });

  return { count, increment, decrement };
}
</script>
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <div class="flex flex-col items-center justify-center">
    <button
      @click="decrement"
      class="bg-blue-500 text-white p-2 rounded"
    >
      Decrement
    </button>
    <p class="text-lg my-4">Count: {{ count }}</p>
    <button
      @click="increment"
      class="bg-green-500 text-white p-2 rounded"
    >
      Increment
    </button>
  </div>
</template>

<script setup lang="ts">
import { useExampleLogic } from './useExampleLogic';

const { count, increment, decrement } = useExampleLogic(0);
</script>

6. 列表组件模式

组件中的大型列表会导致模板混乱和难以管理。解决方案是将 v-for 循环逻辑抽象到一个子组件中。

这可以简化父组件,并将迭代逻辑封装在专门的列表组件中,保持整洁。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- 之前:在父组件中直接使用 v-for -->

<template>
  <div v-for="item in list" :key="item.id">
    <!-- 每个项目的代码 -->
  </div>
</template>

<!-- 之后:将 v-for 抽象到子组件中 -->

<template>
  <NewComponentList :list="list" />
</template>

7. 保留对象模式

将整个对象传递给组件,而不是单个属性,可以简化组件并使其更具未来可扩展性。

然而,这种方法可能会造成对对象结构的依赖,因此不太适合通用组件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- 使用整个对象 -->

<template>
  <CustomerDisplay :customer="activeCustomer" />
</template>

<!-- CustomerDisplay.vue -->

<template>
  <div>
    <p>Name: {{ customer.name }}</p>
    <p>Age: {{ customer.age }}</p>
    <p>Address: {{ customer.address }}</p>
  </div>
</template>

8. 控制器组件

Vue 中的控制器组件弥合了 UI(谦逊组件)和业务逻辑(可组合函数)之间的差距。

它们管理状态和交互,协调应用程序的整体行为。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- TaskController.vue -->

<script setup>
import useTasks from './composables/useTasks';

// 可组合函数包含业务逻辑
const { tasks, addTask, removeTask } = useTasks();
</script>

<template>
  <!-- 谦逊组件提供 UI -->
  <TaskInput @add-task="addTask" />
  <TaskList :tasks="tasks" @remove-task="removeTask" />
</template>

9. 策略模式

策略模式非常适合处理 Vue 应用程序中复杂的条件逻辑。

它允许根据运行时条件在不同组件之间动态切换,从而提高代码的可读性和灵活性。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <component :is="currentComponent" />
</template>

<script setup>
import { computed } from 'vue';
import ComponentOne from './ComponentOne.vue';
import ComponentTwo from './ComponentTwo.vue';
import ComponentThree from './ComponentThree.vue';

const props = defineProps({
  conditionType: String,
});

const currentComponent = computed(() => {
  switch (props.conditionType) {
    case 'one':
      return ComponentOne;
    case 'two':
      return ComponentTwo;
    case 'three':
      return ComponentThree;
    default:
      return DefaultComponent;
  }
});
</script>

10. 隐藏组件模式

隐藏组件模式涉及根据组件的使用方式,将复杂组件拆分成更小、更专注的组件。

如果不同的属性集是独占地一起使用的,则表明可以将组件进行拆分。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- 重构之前 -->

<template>
  <!-- 实际上是一个“图表”组件 -->
  <DataDisplay
    :chart-data="data"
    :chart-options="chartOptions"
  />

  <!-- 实际上是一个“表格”组件 -->
  <DataDisplay
    :table-data="data"
    :table-settings="tableSettings"
  />
</template>

<!-- 重构之后 -->

<template>
  <Chart :data="data" :options="chartOptions" />
  <table :data="data" :settings="tableSettings" />
</template>

11. 内部交易模式

内部交易模式解决了 Vue 中父组件和子组件过度耦合的问题。通过在必要时将子组件内联到父组件中,我们可以进行简化。

这个过程可以使组件结构更加连贯,减少碎片化。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- ParentComponent.vue -->

<template>
  <div>
    <!-- 这个组件使用来自父组件的所有内容。

    它起什么作用呢? -->
    <ChildComponent
      :user-name="userName"
      :email-address="emailAddress"
      :phone-number="phoneNumber"
      @user-update="(val) => $emit('user-update', val)"
      @email-update="(val) => $emit('email-update', val)"
      @phone-update="(val) => $emit('phone-update', val)"
    />
  </div>
</template>

<script setup>
defineProps({
  userName: String,
  emailAddress: String,
  phoneNumber: String,
});

defineEmits(['user-update', 'email-update', 'phone-update']);
</script>

12. 长组件模式

什么算作“过长”的组件?

当它变得难以理解时。

长组件原则鼓励创建自文档化、命名清晰的组件,提高代码质量和可理解性。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- 之前:一个冗长且复杂的组件 -->

<template>
  <div>
    <!-- 大量 HTML 和逻辑 -->
  </div>
</template>

<!-- 之后:分解成更小的组件,

名称告诉你代码的作用。 -->

<template>
  <ComponentPartOne />
  <ComponentPartTwo />
</template>

总结

学习 Vue 设计模式,就像学习一门新的语言,能够让你更深入地理解 Vue 的工作原理,写出更健壮、更灵活、更可扩展的代码。

希望这篇文章能让你对 Vue 设计模式有一个更深的了解,并帮助你在实际开发中应用这些技巧,写出更优秀的 Vue 代码!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端Q 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
[译] 用 Vue 3 Composition API 实现 React Context/Provider 模式
原文:https://markus.oberlehner.net/blog/context-and-provider-pattern-with-the-vue-3-composition-api/
江米小枣
2020/07/06
1.8K0
Vue3 学习笔记 —— (一)深入理解组合式 API
Vue3 是向下兼容 Vue2 API 的,但是 Vue3 中提供了一种全新的 Composition API
Gorit
2021/12/08
7480
Vue3 学习笔记 —— (一)深入理解组合式 API
vue3之Composition API详解
没有Composition API之前vue相关业务的代码需要配置到option的特定的区域,中小型项目是没有问题的,但是在大型项目中会导致后期的维护性比较复杂,同时代码可复用性不高。Vue3.x中的composition-api就是为了解决这个问题而生的
前端进阶之旅
2021/10/16
2.1K0
vue3之Composition API详解
【译】Vue 3 Composition API: Ref vs Reactive
Vue 3.0发布至今已经大半年过去了,我从最初的Option API的思维转换成Composition API花了很长时间,在使用过程中也出现了很多问题。我们都知道Ref和Reactive都是定义响应式数据的方式,而我在初学的时候从网上的大部分博客只得出过一个结论:Ref是定义基本类型数据,Reactive是定义引用类型数据的,但随着后面的实践发现,其实并不是很严谨,于是我找了这么一篇文章,我觉得讲得很好,便有了今天的翻译。下面的原文翻译采用意译并非直译,如有错误,请诸君批评与指正。
前端达人
2021/05/11
2K0
Vue3,用组合的方式来编写更好的代码(1/5)
它们让你把小块的逻辑提取到函数中,我们可以轻松地重复使用,这样的代码更容易编写和阅读。
前端小智@大迁世界
2022/06/27
8330
使用 Vue 3 与 TypeScript 构建 Web 应用: Todo
引言 界面: Vue.js 3 JavaScript 超集: TypeScript 包管理器: pnpm 前端工程化/打包: Vite 路由: Vue Router 状态管理: Pinia CSS 预处理器: Less 代码格式化: Prettier 代码质量: ESLint 预览
yiyun
2023/07/17
1.2K0
使用 Vue 3 与 TypeScript 构建 Web 应用: Todo
vue3的setup还能这么用?
接收一个props和context函数并且将setup内的内容通过return暴露给组件的其余部分。
inline705
2021/12/09
1.1K0
vue3的setup还能这么用?
Vue3, setup语法糖、Composition API全方位解读
支持绑定多个v-model,v-model 是 v-model:modelValue 的简写
yyds2026
2022/09/26
3.1K0
Vue.js 3 使用 Vuex 进行状态管理的综合指南
Vue.js 因其简单性、反应性和强大的生态系统而在前端开发人员中获得了广泛的欢迎。随着 Vue.js 3 的发布,Vue 应用程序中的状态管理变得更加高效和灵活。在本文中,我们将深入探讨 Vue.js 3 状态管理,涵盖基本概念并提供实际示例。
zayyo
2023/10/13
1.1K0
vue3基础ref,reactive,toRef ,toRefs 使用和理解
在 Vue 3 中,ref、reactive、toRef 和 toRefs 是用于响应式数据管理的重要工具。理解它们的使用方式和区别对于有效地利用 Vue 3 的响应式系统至关重要。以下是对这些工具的详细解释和示例。
肥晨
2024/08/27
5380
vue3基础ref,reactive,toRef ,toRefs 使用和理解
Vue 状态管理未来样子
随着Vue 3越来越受重视并成为默认版本,许多事情正在发生变化,生态系统逐渐完善中。直到最近,Vue3 的状态管理默认推荐的是使用 Pinia。这节课,我们根据项目的规模,探索不同的状态管理方式,并尝试预测 Vue 中状态管理的未来会是什么样子。
前端小智@大迁世界
2022/09/23
6580
围绕Vue 3 Composition API构建一个应用程序,包含一些最佳实践!
Vue 3已经发布了一年,它的主要新功能是:Composition API。从2021年秋季开始,推荐新项目使用Vue 3的 script setup 语法,所以希望我们能看到越来越多的生产级应用程序建立在Vue 3上。
前端小智@大迁世界
2022/09/08
1.3K0
vue3的Composition API
Composition API 也叫组合式API, 是在vue3中新引入的一种API,vue2中已经有option API了,那为什么要新稿这么一套呢,其实主要原因是要解决vue2中的option API的在处理复杂组件逻辑的局限性,例如逻辑分散、代码复用性差、类型推断困难、组件组织混乱、响应式系统限制、模板逻辑复杂性、组件测试困难等问题。为此Composition API通过函数的方式来组织代码,使得逻辑更加模块化和可组合,这就变得很灵活。
iwhao
2024/08/04
1090
vue3实战-完全掌握ref、reactive
知道大家使用 Vue3 的时候有没有这样的疑惑,“ref、rective 都能创建一个响应式对象,我该如何选择?”,“为什么响应式对象解构之后就失去了响应式?应该如何处理?” 今天咱们就来全面盘点一下 ref、reactive,相信看完你一定会有不一样的收获,一起学起来吧!
yyds2026
2022/11/01
3.5K0
我常用的几个 VueUse 最佳组合,推荐给你们!
Vueuse拥有大量出色的组合。但是量太大,要把它们全部看完可能会让人抓不到重点。下面来介绍一些有用到的组合,它们如下:
前端小智@大迁世界
2022/09/09
2.7K0
我常用的几个 VueUse 最佳组合,推荐给你们!
vue3简易入门剖析
,发音同 “veet”)是一种新型前端构建工具,能够显著提升前端开发体验。它主要由两部分组成:
用户9184480
2024/12/13
3730
使用 Vue.js 和 JavaScript 在 Web 应用程序中下载 PDF 文件
首先,我们将创建一个 Vue.js 组件,其中包含单击按钮时下载 PDF 文件的必要逻辑。
海拥
2023/05/02
3.1K0
最全系列的vue3入门教程『图文并茂』
Vue 3 是一个流行的开源JavaScript框架,用于构建用户界面和单页面应用。它带来了许多新特性和改进,包括更好的性能、更小的打包大小、更好的TypeScript支持、全新的组合式 API,以及一些新的内置组件。
linwu
2023/07/27
5K0
最全系列的vue3入门教程『图文并茂』
vue3 -- 通过简单示例,聊一聊Composition API
在 vue3 版本之前,我们复用组件(或者提取和重用多个组件之间的逻辑),通常有以下几种方式:
奋飛
2021/08/30
5200
vue3 -- 通过简单示例,聊一聊Composition API
vue3 -- 通过简单示例,聊一聊Composition API
在 vue3 版本之前,我们复用组件(或者提取和重用多个组件之间的逻辑),通常有以下几种方式:
奋飛
2020/12/09
1.9K0
推荐阅读
相关推荐
[译] 用 Vue 3 Composition API 实现 React Context/Provider 模式
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验