如何组织 Vue 项目

介绍

在启动 Vue 项目时,思考项目结构至关重要。主要考虑因素是预期项目的规模。在本篇博文中,我将探讨适用于不同规模 Vue 项目的各种结构。这个考虑与康威定律相吻合:

“设计系统的组织受限于产生这些组织沟通结构的设计。” - 梅尔·康威

基本上,康威定律暗示了您的 Vue 应用程序的架构将固有地反映出您的组织架构,从而影响您应该如何规划项目的结构。

一些常规规则

在我们开始介绍不同的项目结构之前,我想强调一些通用的规则,这些规则适用于每种结构,大部分来自于官方的 Vue 风格指南。

基础组件命名

为您的 UI 组件使用前缀

不好的

components/
|- MyButton.vue
|- VueTable.vue
|- Icon.vue

好的

components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue

紧密耦合的组件名称

将紧密耦合的组件名称放在一起

不好的

components/
|- TodoList.vue
|- TodoItem.vue
|- TodoButton.vue

好的

components/
|- TodoList.vue
|- TodoListItem.vue
|- TodoListItemButton.vue

组件名称中单词的顺序

组件名称应该以最高级别(通常是最通用的)的单词开头,并以描述性的修改词结尾。

不好的

components/
|- ClearSearchButton.vue
|- ExcludeFromSearchInput.vue
|- LaunchOnStartupCheckbox.vue
|- RunSearchButton.vue
|- SearchInput.vue
|- TermsCheckbox.vue

好的

components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputQuery.vue
|- SearchInputExcludeGlob.vue
|- SettingsCheckboxTerms.vue
|- SettingsCheckboxLaunchOnStartup.vue

测试

决定如何组织您的测试以及将它们放置在何处可能是另一个博文的主题。在本文中,我们将探讨将测试放置在单独的文件夹中,其中每个测试文件反映源代码。或者,您可以将测试文件放置在它们所测试的文件旁边。这两种方法都是有效的。

方法1:单独的测试文件夹
/vue-project
|-- /src
|   |-- /components
|   |   |-- MyComponent.vue
|   |-- /views
|   |   |-- HomeView.vue
|-- /tests
|   |-- /components
|   |   |-- MyComponent.spec.js
|   |-- /views
|   |   |-- HomeView.spec.js
|-- package.json
|-- ...
方法2:内联测试文件
/vue-project
|-- /src
|   |-- /components
|   |   |-- MyComponent.vue
|   |   |-- MyComponent.spec.js
|   |-- /views
|   |   |-- HomeView.vue
|   |   |-- HomeView.spec.js
|-- package.json
|-- ...

扁平式方法

在启动小规模 Vue 项目(如概念验证)时,您可能更喜欢简单直接的文件夹结构以避免复杂性:

/src
|-- /components
|   |-- BaseButton.vue
|   |-- BaseCard.vue
|   |-- PokemonList.vue
|   |-- PokemonCard.vue
|-- /composables
|   |-- usePokemon.js
|-- /utils
|   |-- validators.js
|-- /layout
|   |-- DefaultLayout.vue
|   |-- AdminLayout.vue
|-- /plugins
|   |-- translate.js
|-- /views
|   |-- Home.vue
|   |-- PokemonDetail.vue
|-- /router
|   |-- index.js
|-- /store
|   |-- index.js
|-- /assets
|   |-- /images
|   |-- /styles
|-- /tests
|   |-- ...
|-- App.vue
|-- main.js

原子设计

对于较大的 Vue 应用程序,采用原子设计方法可能是有利的。这种方法将组件组织成从简单到复杂的层次结构:

  • 原子(Atoms):基本元素(例如按钮、图标)
  • 分子(Molecules):由原子组成的组合体(例如搜索栏)
  • 有机体(Organisms):复杂组件(例如导航栏)
  • 模板(Templates):显示组件结构的布局
  • 页面(Pages):具有真实数据的实际 UI 屏幕

这种方法确保了可扩展性和可维护性,并且能够在简单和复杂组件之间平滑过渡。

原子设计图

/src
|-- /components
|   |-- /atoms
|   |   |-- AtomButton.vue
|   |   |-- AtomIcon.vue
|   |-- /molecules
|   |   |-- MoleculeSearchInput.vue
|   |   |-- MoleculePokemonThumbnail.vue
|   |-- /organisms
|   |   |-- OrganismPokemonCard.vue
|   |   |-- OrganismHeader.vue
|   |-- /templates
|   |   |-- TemplatePokemonList.vue
|   |   |-- TemplatePokemonDetail.vue
|-- /pages
|   |-- PageHome.vue
|   |-- PagePokemonDetail.vue
|-- /composables
|   |-- usePokemon.js
|-- /utils
|   |-- validators.js
|-- /layout
|   |-- LayoutDefault.vue
|   |-- LayoutAdmin.vue
|-- /plugins
|   |-- translate.js
|-- /router
|   |-- index.js
|-- /store
|   |-- index.js
|-- /assets
|   |-- /images
|   |-- /styles
|-- /tests
|   |-- ...
|-- App.vue
|-- main.js

模块

随着项目规模的扩大,考虑采用模块化的单块架构。这种结构封装了每个功能或领域,增强了可维护性,并为可能的演变向微服务方向做好了准备:

/src
|-- /core
|   |-- /components
|   |   |-- BaseButton.vue
|   |   |-- BaseIcon.vue
|   |-- /models
|   |-- /store
|   |-- /services
|   |-- /views
|   |   |-- DefaultLayout.vue
|   |   |-- AdminLayout.vue
|   |-- /utils
|   |   |-- validators.js
|-- /modules
|   |-- /pokemon
|   |   |-- /components
|   |   |   |-- PokemonThumbnail.vue
|   |   |   |-- PokemonCard.vue
|   |   |   |-- PokemonListTemplate.vue
|   |   |   |-- PokemonDetailTemplate.vue
|   |   |-- /models
|   |   |-- /store
|   |   |   |-- pokemonStore.js
|   |   |-- /services
|   |   |-- /views
|   |   |   |-- PokemonDetailPage.vue
|   |   |-- /tests
|   |   |   |-- pokemonTests.spec.js
|   |-- /search
|   |   |-- /components
|   |   |   |-- SearchInput.vue
|   |   |-- /models
|   |   |-- /store
|   |   |   |-- searchStore.js
|   |   |-- /services
|   |   |-- /views
|   |   |-- /tests
|   |   |   |-- searchTests.spec.js
|-- /assets
|   |-- /images
|   |-- /styles
|-- /scss
|-- App.vue
|-- main.ts
|-- router.ts
|-- store.ts
|-- /tests
|   |-- ...
|-- /plugins
|   |-- translate.js

功能分割设计

功能分割设计是一种组织大型和长期项目以便更易于管理和扩展的方法。此方法将应用程序分成不同的层,每个层具有特定的角色:

  • 应用程序(App):全局设置、样式和提供者。
  • 页面(Pages):使用实体、功能和小部件构建完整页面。
  • 小部件(Widgets):将实体和功能组合成一致的 UI 块,如 IssueList 或 UserProfile。
  • 功能(Features):处理添加价值的用户交互,例如发送评论、添加到购物车或搜索用户。
  • 实体(Entities):表示核心业务模型,如用户、产品和订单。
  • 共享(Shared):提供与特定业务逻辑无关的可重用实用程序和组件,如 UIKit、库和 API。
/src
|-- /app
|   |-- App.vue
|   |-- main.js
|   |-- app.scss
|-- /processes
|-- /pages
|   |-- Home.vue
|   |-- PokemonDetailPage.vue
|-- /widgets
|   |-- UserProfile.vue
|   |-- PokemonStatsWidget.vue
|-- /features
|   |-- pokemon
|   |   |-- CatchPokemon.vue
|   |   |-- PokemonList.vue
|   |-- user
|   |   |-- Login.vue
|   |   |-- Register.vue
|-- /entities
|   |-- user
|   |   |-- userService.js
|   |   |-- userModel.js
|   |-- pokemon
|   |   |-- pokemonService.js
|   |   |-- pokemonModel.js
|-- /shared
|   |-- ui
|   |   |-- BaseButton.vue
|   |   |-- BaseInput.vue
|   |   |-- Loader.vue
|   |-- lib
|   |   |-- api.js
|   |   |-- helpers.js
|-- /assets
|   |-- /images
|   |-- /styles
|-- /router
|   |-- index.js
|-- /store
|   |-- index.js
|-- /tests
|   |-- featureTests.spec.js

这种设置非常适合大型项目,因为它使得项目更容易扩展和保持整洁。要了解有关这些层如何工作的更多详细信息,请查看官方的功能分割设计文档。

功能分割设计图

微前端

微前端将微服务的思想应用于 Web 应用程序的前端部分。这意味着不同的团队可以独立处理 Web 应用程序的不同部分,而不会相互干扰。每个部分,或“微前端”,都可以独立运行,并可以单独更新。这是一个 SPA 的基本概述。请注意,本文不会深

入介绍微前端的工作原理。

  • 应用程序 Shell:这是控制主要布局和站点路由的主要控制器。它将所有微前端连接在一起。
  • 分解的 UI:每个微前端都专注于应用程序的特定部分。它们可以使用不同的技术进行开发,并可以分别更新。

Image description

主要优点是微前端让团队可以在不等待其他团队的情况下更新应用程序的各个部分,这可以加快开发速度。然而,这种设置可能会使应用程序更复杂,难以管理和保持一致。

有用的资源:

  • 微前端 - 将微服务思想扩展到前端开发
  • 马丁·福勒关于微前端

这种策略非常适合具有多个开发团队的大型、复杂项目。每个团队都可以专注于特定的业务需求,而不会影响其他团队的工作,可能使用最适合其部分的技术。


结论

Image description

希望现在清楚了,您应该选择一个反映您组织规模和复杂性的结构。此外,更先进的结构将值得一篇独立的博文;我只是想为您提供一个良好的概述。一般来说,您的团队越大、越复杂,或者拥有更多的团队,您就越应该朝着更好地分隔这些概念的结构努力。基本上,您团队的结构将指导您确定最适合您需求的项目结构。

方法描述优点缺点
扁平式方法简单的结构,适合小项目或概念验证。- 易于实施 - 最小设置- 不可扩展 - 随着项目增长而混乱
原子设计基于组件复杂性的分层结构。- 可扩展 - 有组织 - 可重用组件- 管理层面的开销 - 复杂的设置
模块封装功能的模块化结构。- 可扩展 - 封装特性- 可能存在重复 - 可能变得复杂
功能分割设计将项目组织成功能层和切片。- 高内聚 - 明确的功能分离- 初始复杂性 - 需要彻底规划
微前端应用程序的每个部分都可以单独部署。- 独立部署 - 可扩展- 复杂性高 - 需要团队之间的协调

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

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

相关文章

C语言之指针初阶

目录 前言 一、内存与地址的关系 二、指针变量 三、野指针 四、const 五、传值调用与传址调用 总结 前言 本文主要介绍C语言指针的一些基础知识,为后面深入理解指针打下基础,因此本文内容主要包括内存与地址的关系,指针的基本语法&…

WebRTC实时音视频通话之语音通话设计与实践

一、背景 在移动互联网流量时代,很多业务场景都有音视频通信的需求,比如IM场景,除了文字交流还需要音视频通话进行实时交互。为了帮助58、赶集、安居客等业务线更好的为用户提供服务,节约沟通成本,提升效率&#xff0…

【Linux】19. 习题②

2022-11-12_Linux环境变量 1. 分页存储(了解) 一个分页存储管理系统中,地址长度为 32 位,其中页号占 8 位,则页表长度是__。 A.2的8次方 B.2的16次方 C.2的24次方 D.2的32次方 【答案解析】A 页号即页表项的序号,总共占8个二进制…

go语言之控制结构2

1.for结构 如果想要重复执行某些语句&#xff0c;Go 语言中您只有 for 结构可以使用 1.1 基于计数器的迭代 基本格式为&#xff1a; for 初始化语句; 条件语句; 修饰语句 {} 例子1&#xff1a; package mainimport "fmt"func main() {for i : 0; i < 5; i {f…

STM32的FLASH学习笔记

不同型号的 STM32&#xff0c;其 FLASH 容量也有所不同&#xff0c;最小的只有 16K 字节&#xff0c;最大的则达到了1024K 字节。大容量产品的闪存模块组织如图所示&#xff1a; STM32 的闪存模块由&#xff1a;主存储器、信息块和闪存存储器接口寄存器等 3 部分组成。 ​ ①主…

骨架油封在工业应用中的重要性

为什么我们会选择使用山峰骨架油封?这个问题直接关系到工业生产的效率和成本管理。山峰骨架油封凭借其卓越的性能和多重优势已经成为众多工程师和维护人员的很好选。 全方位的应用优势 山峰骨架油封不仅在密封效果上表现出色&#xff0c;同时还适用于各种工业应用场景。无论…

路由跟踪,追踪请求的网址链接情况

追踪请求的网址链接情况,多节点情况可查看是否有节点拒绝响应 linux&#xff1a; traceroute open.XXX.com windows tracert open.XXX.com

Java环境搭建(二)Notepad++和IDEA的下载

Notepad&#xff08;不推荐使用&#xff09; 高级记事本 下载地址 Notepad (juxinwk1.cn) 下载安装后一直下一步就可以了 注&#xff1a;改一下路径还有建立快捷方式&#xff08;自己选择&#xff09; IDEA 集成环境 下载地址 IntelliJ IDEA – the Leading Java and Kotl…

React 第三十二章 虚拟DOM

面试题&#xff1a;什么是虚拟DOM&#xff1f;其优点有哪些&#xff1f; 标准且浅显的答案 虚拟dom本质上就是一个普通的 JS 对象&#xff0c;用于描述视图的界面结构 虚拟 DOM 最早是由 React 团队提出来的&#xff0c;因此 React 团队在对虚拟 DOM 的定义上面有绝对的话语权。…

若依-生成主子表

1. sql语句建表导入到数据库中&#xff1a; -- ---------------------------- -- Table structure for t_ques————主表 -- ----------------------------CREATE TABLE ques (ques_id INT NOT NULL AUTO_INCREMENT COMMENT Id,name VARCHAR(255) NOT NULL COMMENT 测评名称…

未授权访问:Rsync 未授权访问漏洞

目录 1、漏洞原理 2、环境搭建 3、未授权访问 4、利用rsync下载任意文件 5、利用rsync反弹shell 防御手段 今天继续学习各种未授权访问的知识和相关的实操实验&#xff0c;一共有好多篇&#xff0c;内容主要是参考先知社区的一位大佬的关于未授权访问的好文章&#xff0c…

ApiHug - 闭门造车, 出门合辙

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace The Nex…

RocketMQ:新增consumer消费组group从最新消息开始消费skip last offset message

场景 想创建一个新的consumer去消费一个已经再使用的topic时&#xff0c;默认情况下会从topic中的第一条消息开始消费&#xff0c;大多数情况是需要从最新的消息开始。然后再使用CONSUME_FROM_LAST_OFFSET设置时并不会对新的consumer生效&#xff0c;它只是在停用consumer重新启…

Vue学习之:在 vue2 中引入 pdf.js 并配置使其能工作

安装 不同版本的 pdfjs 在 node_modules 中的目录不太一样&#xff0c;如果你想让他正常运行就按照我下面的来确保你的 nvm 版本是 18.17 如果不是的话&#xff0c;建议你配置跟我调成一样的&#xff0c;否则很容易出问题 nvm install 18.17.0 nvm use 18.17.0安装 pdfjs&…

代码随想录算法训练营day25 | 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

669. 修剪二叉搜索树 看题解做出来的 class Solution:def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:if not root:return Noneif root.val < low:return self.trimBST(root.right, low, high)if root.val > high:return…

【栈的应用】中缀和后缀表达式 {中缀转后缀表达式;中缀表达式求值;后缀表达式求值}

中缀转后缀表达式 在中缀变后缀时&#xff0c;操作数的顺序不会发生变化&#xff0c;只有运算符的顺序可能发生变化。同时又没有括号。所以在转换的过程中&#xff0c;只要碰到操作数&#xff0c;可以直接输出&#xff0c;而遇到运算符和括号进行相应的处理即可。 转换原则如…

SD8063音频功率放大器5V音频功率放大器低功耗

SD8063是一个双桥接音频功率放大器&#xff0c;当 连接到一个5V的pp时&#xff0c;将ver2.2W toa4ΩL oad(No电话)or2.5瓦至a3欧洛a(第2项) THDN含量小于an1.0%此外&#xff0c;耳机输入引 脚允许放大器在单端模式下工作时&#xff0c;驾驶立 体声耳机。 Boomer音频功率放大器的…

Java静态方法和实例方法有何不同?

在Java中&#xff0c;方法可以分为静态方法和实例方法。这两种方法的区别在于它们的调用方式、访问权限以及应用场景。理解这两者的区别对于掌握Java编程非常重要。下面我们将详细剖析这两者的区别&#xff0c;并通过代码示例加以说明。 1. 调用方式 静态方法的调用 静态方法…

代码随想录算法训练营day26 | 77. 组合

理论 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。 回溯法并不是什么高效的算法。因为回溯的本质是穷举&#xff0c;穷举所有可能&#xff0c;然后选出我们想要的答案&#xff0c;如果想让回溯法高效一些&#xff0c;可以加一些剪枝的操作&#xff0c;但也改…

MySQL单表查询案例演示

目录 一、创建数据库lianxi 二、选择数据库为lianxi 三、新建一个数据表grade&#xff0c;在grade表中插入数据 四、开始进行查询操作&#xff08;验证表中数据&#xff09; 1、查询1945班的成绩信息 2、查询1945班&#xff0c;语文成绩大于60小于90的成绩信息 3、查询学…