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

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

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

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 字

Web应用实现在手机端访问和使用方案

1. 背景 当前的后台管理系统主要负责云平台和云服务器的管理,并且是以Web应用的形式在使用。但是,当出现服务器紧急情况或需要进行平台注册审核时,如果这些任务发生在非工作时间,例如在通勤路上,我们就无法使用PC浏览器进行访问和操作,这显然是不方便的。另外,由于后台管理系统仅供内部人员使用,我们只需要它能满足基本的查看和配置需求,对于便利性和美观性并没有太高要求。因此,将Web端的所有功能移植到手机端并开发一个App,显然很不划算。毕竟,每当Web端功能迭代时,App端也需要同步更新,这意味着同一功能需要实现两次,所以,开发App的方案就不考虑了。 2. 方案 2.1 方案一:使用手机Edge、Firefox浏览器访问使用【推荐】 使用手机通过Edge或Firefox浏览器访问时,设置为“查看桌面网站”(Firefox中称为桌面版网站开关),即可浏览平台的完整布局,并通过手势放大和缩小来居中展示所需内容,操作便捷。 可将后台管理系统的管理平台添加到手机主屏幕,实现快速访问。 以TDesign页面模板演示效果。 2.2 方案二:当前页面 + 全屏 创建一个专为手机端使用的手机端菜单,仅显示关注页面,手机端访问时读取该菜单显示。 利用@media媒体查询调整各页面布局,例如筛选条件等,以避免布局错乱。 默认情况下,只能在手机横屏模式下使用,提供一个全屏按钮,点击后将当前页面全屏化,以争取更多展示空间。 2.3 方案三:远程软件控制电脑访问使用 使用远程软件(如向日葵)访问电脑,然后在手机端通过手势放大和缩小进行操作。效果与方案一相似,但存在以下不足: 输入时需要手动打开键盘。 页面有滚动条时操作繁琐。 连接可能不稳定,画质不佳。 3. 结论 方案一无需额外开发成本,只需在指定手机浏览器上使用即可。 方案二需要额外开发,且最终呈现效果可能不如方案一。 方案三存在上述提到的缺点。 综合考虑,推荐采用方案一。

2024-11-01 · 1 分钟 · 29 字