前端业务组件封装与管理的解决方案

1. 前言 在前端开发中,业务组件的封装与管理是一个常见的难题。当多个项目共用同一个业务组件时,如何平衡不同项目的需求差异,同时保持组件的可维护性和可扩展性,成为了一个亟待解决的问题。 2 如何应对多项目需求差异 在业务组件封装过程中,我们常常会遇到这样的问题:项目 A 和项目 B 都使用了某个业务组件,但项目 A 迭代了需求,而这个需求在项目 B 中却用不到。如果这次为了满足项目 A 的需求而修改组件,那么未来项目 B 也可能出现类似但不完全相同的需求,难道每次都要通过特判来解决吗? 实际上,业务组件的问题并非孤立存在,而是整个前端项目开发流程中的一个环节。我们需要从更高的层次、更宏观的角度去看待,梳理整个前端项目的开发流程,预见可能面临的问题,并逐一讨论解决方案、进行应用和验证,而不仅仅是解决业务组件自身的问题。 3. 期望的应用场景 我们期望构建一个高效、灵活的前端开发流程,具体场景如下: 提供一个基础的项目模板,其中包含常用的业务组件,如登录注册、首页、个人中心、用户管理等。这样,新的项目可以直接基于模板启动,减少重复工作。 通过动态配置主题色等功能,满足客户项目的定制化需求。例如,不同客户可能对界面风格有不同偏好,通过风格配置平台可以快速实现定制。 在菜单管理中配置好路由,从业务组件库中引入所需的业务组件。如果现有组件不满足需求,则可以迭代现有组件或新增组件。 4. 通用性与灵活性 业务组件应具备通用功能,能够满足大部分项目的需求,从而减少重复开发,提高开发效率。当遇到特殊需求时,可以采用组合式函数的方式,将逻辑单独抽离出来复用。同时,提供样式自定义功能,通过增加一个 .vue 文件来实现样式定制,从而复用组合式函数。这种做法既保持了组件的通用性,又提供了足够的灵活性来应对不同项目的需求。 5. 确保质量和稳定性 为了保证业务组件的质量和稳定性,单元测试是必不可少的环节。主要包括以下两个方面: 对组件的逻辑代码进行测试,确保其功能正确无误。 测试组件之间的交互是否符合预期,例如父子组件之间的数据传递、事件触发等。 6. 满足多样化需求 业务组件的风格动态设置是一个关键问题。以当前常见的明亮和暗黑风格为例,问题的根本原因并不在于组件自身,而在于项目。因此,需要设置的不是业务组件的主题,而是项目的主题。而项目是基于我们提供的项目模板开发的,所以项目模板需要提供风格动态设置功能。 最佳的实现方式是通过可视化页面进行配置,然后生成 CSS 文件,将其引入到项目中进行配置。这就需要开发一个可视化主题配置平台,比如 Arco Design Lab 平台(平台使用指南),能够很好地满足这一需求。 7. 总结 通过建立一套完整的开发规范、提供风格动态设置功能,我们可以有效地解决多项目需求差异的问题,提高开发效率和质量。

2025-04-26 · 1 分钟 · 48 字

新旧项目 Element Plus 组件库版本兼容方案

前言 因为之前组件库是基于Element Plus开发版本1.0.2-beta.71封装的,而组件库-R2是基于Element Plus正式版本封装的,如果要使用组件库-R2,就需要把版本升级到正式版来解决,但是因为开发版本和正式版在用法上面、组件方面有很大差异,升级之后势必会有各式各样的问题。之前想过一个项目两个Element Plus版本共存,但是每个组件的命名都是一样的。每个组件库都是基于Element Plus的组件封装的,如果两个组件库共存,到时我们自己封装的组件,里面使用的<el-xxx>应该使用哪个Element Plus版本呢? npm i element-plus@1.0.2-beta.71 方案一:beta 和 stable 两版本共存 ==beta:==使用oelement-plus 命名安装包、oel-button 组件命名 ==stable:==使用自定义命名空间 npm 或 yarn 使用别名同时安装同一个包的两个版本 1.0.2-beta.71 为什么要做这次的破坏性变动 Why making such breaking changes in 1.1.0-beta.1 https://github.com/element-plus/element-plus/discussions/3020 方案二:Element Plus 升级至新版 旧版升级至新版改动很大,收益很少。但是有个好处就是不背历史包袱。 最理想的方案,但是成本太高,以前的功能已经正常了,没必要额外花费这些时间。 ==升级至新版的契机应该是,后面用户体验,变动整体结构。==

2025-04-18 · 1 分钟 · 38 字

Pinia持久化插件 pinia-plugin-persistedstate 的基本使用

前言 在Vue项目开发过程中,状态管理是至关重要的环节。随着Pinia的推出,它凭借更简洁直观的API,逐渐成为Vuex的有力替代品。为了进一步简化本地存储的管理,pinia-plugin-persistedstate 插件应运而生,它能够帮助开发者轻松实现状态的持久化。 本文将详细介绍如何使用该插件,并解决在跨项目登录时由于数据格式不一致导致的问题。 安装插件 在项目的根目录下运行以下命令以安装插件: npm i pinia-plugin-persistedstate 随后,在main.ts文件中引入并配置插件: import { createPinia } from 'pinia' import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' const pinia = createPinia() pinia.use(piniaPluginPersistedstate) 完成以上步骤后,Pinia便具备了持久化功能。 基本使用 假设我们需要管理用户信息userInfo,并将其持久化到本地存储中,那么就可以这样实现: import { defineStore } from 'pinia'; export const useUserInfoStore = defineStore('userInfo', { state: () => ({ userInfo: null as any }), persist: true, actions: { setUserInfo(info: any) { this.userInfo = info; } } }); 按照上述配置,用户信息将自动持久化到本地存储中。 仅持久化对象中的特定字段 在实际应用中,开发者可能会面临跨项目登录时出现的兼容性问题。具体场景为:用户在项目A完成登录操作后,随即打开项目B。由于Token的复用机制,项目B会自动完成登录流程。然而,在尝试获取用户信息userInfo时,由于不同项目对数据格式的定义存在差异,导致项目B无法准确获取用户的ID,进而无法基于此ID发起正确的网络请求。具体表现如下: 项目A的数据格式:{ name: 'xiaoming', nick_name: '小明', userID: '9527' } 项目B的数据格式:{ userInfo: { name: 'xiaoming', nick_name: '小明', userID: '9527' } } 由于插件默认将整个state对象存储起来,导致数据多了一层userInfo外壳,从而引发格式不一致的问题。 为了去掉userInfo这一层外壳,我们需要自定义序列化和反序列化逻辑。修改后的Store配置如下: import { defineStore } from 'pinia'; export const useUserInfoStore = defineStore('userInfo', { state: () => ({ userInfo: null as any }), persist: { key: 'userInfo', storage: localStorage, paths: ['userInfo'], // 明确声明要持久化的字段 serializer: { serialize: (state: any) => JSON.stringify(state.userInfo), deserialize: (str: string) => ({ userInfo: JSON.parse(str) }) } } as any, actions: { setUserInfo(info: any) { this.userInfo = info; } } }); 经过上述配置,用户信息的存储结构变为{ name: 'xiaoming', nick_name: '小明', userID: '9527' },不再有额外的userInfo外壳,从而解决了跨项目登录时的格式不一致问题。 ...

2025-04-14 · 2 分钟 · 247 字

unplugin-vue-router 的基本使用

1. 前言 在Vue3开发过程中,每次创建新的页面都需要注册路由,需要在src/router.ts中新增页面的路径,并将URL路径映射到组件中,如下所示: import { createMemoryHistory, createRouter } from 'vue-router' import HomePageView from './HomePageView.vue' import DevListView from './DevListView.vue' const routes = [ { path: '/', component: HomePageView }, { path: '/DevListView', component: DevListView }, ] const router = createRouter({ history: createMemoryHistory(), routes, }) 虽然看起来工作量不大,但如果页面特别多,就会感到繁琐。即使是微小的改动,如组件名的修改,也需要在路由文件中反复确认,反复如此就会感到不便。为了简化这部分工作,我想到了一个解决方案,那就是开发一个Vue3菜单路由生成工具,只需填写组件的中文名称,根据树形结构生成一个与routes结构相同的数组,然后替换使用即可。但还是觉得不够好,随后想到既然自己能发现这个问题,别人可能早已有了应对方案。接着,我就发现了 unplugin-vue-router 插件。 2. 配置 2.1 安装 npm install -D unplugin-vue-router 2.2 vite.config.ts import VueRouter from 'unplugin-vue-router/vite' export default defineConfig({ plugins: [ VueRouter({ /* options */ }), // ⚠️ Vue must be placed after VueRouter() Vue(), ], }) 2.3 tsconfig.json { "include": [ // other files... "./typed-router.d.ts" ], "compilerOptions": { // ... "moduleResolution": "Bundler", // ... } } 2.4 vite-env.d.ts /// <reference types="unplugin-vue-router/client" /> 3. 应用 3.1 常规方式 因为项目布局是基于Element Plus组件库的<el-container>搭建的,其中对<e-main>进行了处理,<router-view>是 Vue Router 的一个内置组件,用于渲染匹配当前路由的组件,如下所示: ...

2024-12-29 · 2 分钟 · 286 字

组态页面渲染器通过npm包方式使用页面没有渲染成功的问题

前言 在项目开发过程中,计划将组态页面的渲染器集成到组件库,以 npm 包的形式供后续项目模板复用。如此一来,倘若组态页面渲染出现问题,便能简化修复与迭代工作。 遇到问题 采用本地引入方式开发完成后,切换至 npm 包方式使用,此时面包屑可正常显示,然而组态页面部分却呈现空白状态。 分析问题 既然面包屑显示正常,那就表明通过向组件传入 Router 对象进行相关操作并无问题,毕竟面包屑与组态页面共同构成了项目中的具体功能页面。不可能 Router 有问题,面包屑却还能正常显示。 推测组件打包生成 npm 包后,自身未携带 Vue 环境,致使 Vue 内置特殊元素 <component> 渲染失败,此前使用 Pinia 时就碰到过类似情况。 那么,该如何在组件里创建 Vue 环境呢? 要是不使用 <component>,而改用渲染函数来实现会怎样呢? markRaw 的作用是什么? 利用渲染函数实现后,发现打包成 npm 包使用时依旧出现空白,这就说明并非 <component> 的问题,如此一来,问题范围便缩小到组态页面的数据源上了。 对比本地引用和 npm 包两种方式下的数据请求差异,发现使用 npm 包时,存在接口未发起请求的情况,进而定位到问题根源。 问题原因 由于该渲染器是在项目中使用,其请求的 baseURL 是通过 window.location.origin 获取的。在本地引入使用时,本地开发服务器地址为 http://localhost:3000/,并且在 Vue 项目的 vite.config.ts 中已做代理,所以请求正常。但当把渲染器代码移至组件库并以 npm 包方式使用时,它自行获取的请求地址仍是 http://localhost:3000/,并未经过代理处理,致使请求资源的接口异常,最终造成页面空白。 const baseURL = import.meta.env.DEV ? "http://192.168.50.20" : window.location.origin 总结 解决 Bug 的思路仍有待提升,自己还是过于急于求成了。刚察觉到问题的一点苗头,就贸然行事、妄下结论,实在有些武断。一开始认定是 <component> 的问题,就应当采用排除法,不该如此笃定。实际上,只需用简单示例测试一下,便能排除该选项,也不至于耗费大量精力深入研究如何在组件里创建 Vue 环境?如何用渲染函数实现组件?平白浪费了许多时间。 每次解决完一个 Bug 之后都会觉得,这个算啥问题,真的不值一提。可在解决过程中,却常常感到无奈,好几次都差点放弃。原本代码放在项目中使用正常,非要解耦,感觉像是没事找事。不过,最终还是坚持了下来,觉得应该差不多能弄清楚问题所在了。虽说花费的时间不太划算,就如同这篇文章写得好似没什么价值一般,但总结一下解决 Bug 的心路历程,相信还是会有所收获的。积累到一定程度,便能为自己提供更多面对问题时的视角与启发。 ...

2024-12-20 · 1 分钟 · 77 字