# vue2+tsx-test **Repository Path**: ggbhack/vue2-tsx-testv ## Basic Information - **Project Name**: vue2+tsx-test - **Description**: vue2+tsx-test - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-01-19 - **Last Updated**: 2023-03-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Vue 2.7 + Ant v1.7.8 + vben-admin组件 + vite --- 登录账号+密码 ssjadmin/ssjadmin --- 基于 [Ant Design Pro](https://1x.antdv.com/components/select#API) + [vue2.7](https://v2.cn.vuejs.org/v2/guide/migration-vue-2-7.html) + typescript + vite 搭建的项目 环境和依赖 --- - node - yarn - eslint - vite - typescript - vue2.7 新特性 - [ant-design-vue](https://github.com/vueComponent/ant-design-vue) - Ant Design Of Vue 实现 > 请注意,我们强烈建议本项目使用 [Yarn](https://yarnpkg.com/) 包管理工具,这样可以与本项目演示站所加载完全相同的依赖版本 (yarn.lock) 。由于我们没有对依赖进行强制的版本控制,采用非 yarn 包管理进行引入时,可能由于 Pro 所依赖的库已经升级版本而引入了新版本所导致的问题。 ## 项目运行和发布 --- - 安装依赖 ```dash yarn install ``` - 开发模式运行 ```dash yarn run vite ``` - 编译项目 ```dash yarn run vite-build ``` ## 进度模块 --- - api 接口 - assets 静态文件 - common 公共内容 - enum 公共枚举 - model 公共模型【旧】 - components - [x] STable 自适应高度【已经放弃使用,更改为vben-table】 - config - build vite打包配置【持续优化中】 - generate 动态生成iconify 脚本 - script 打包构建脚本 - vite - plugin vite插件包 - proxy.ts vite代理配置 - constants 常量 - utils.ts 配置工具 - core 核心库【已弃用】 - lazy_use [全局组件引入](src\core\lazy_use.js)【弃用】 - directives 指令【弃用】 - action [按钮权限](src\core\directives\action.js) - layout - locales 多语言配置 - router - generator-router [动态路由菜单](src\router\generator-routers.js) - router-config.js [路由配置](src\router\router.config.js) - permission [路由守卫](src\router\permission.js) - store 状态管理 - index vuex - pinia pinia - utils - propTypes.ts [vueProps的类型工具](src\utils\propTypes.ts) - helper - permission [按钮权限菜单](src\utils\helper\permission.js) - hooks - types 项目用到的类型声明文件 - [x] demo [测试组件专用](src\views\demo\Index.vue) - [x] hello.tsx [tsx 测试文件](src\views\demo\Hello.tsx) ## 开发注意事项 --- > - 打包后请先访问是否有误[项目向上地址](http://ssj.shisuojia.com/#/index) > - api 目录对应 views 目录 > - 原先就在的 api 如果有改动,请新增或是新建对应的目录,方式与原项目混杂太多 > - 新增页面使用 xxx/Index.vue 的方式,如果存在其他的子页面,只需要在相同目录处理即可 > - 新增一个模块/或页面,记得都 readme 更新状态和将文件名添加到模块前以及对应的地址跳转 > - s-table 下面的插槽需要使用 template 使用其他标签会导致 在特定的浏览器显示有误的问题 > - 组件目录使用 components 原来的 modules 遇到就该,没遇到先不动 > - /deep/ 替换为 ::v-deep > - 页面装修 链接跳转[Links](src\common\model\Links.js) > - 页面装修 左侧组件配置[components.data](src\views\page\modules\components\components.data.js) > - 页面装修 组件相关文件[Phone.vue](src\views\page\modules\phone\Phone.vue) > - 页面装修 组件相关文件[Editor.vue](src\views\page\modules\editor\Editor.vue) > - 页面装修 模拟组件数据[Create.vue](src\views\page\Create.vue) [Update.vue](src\views\page\Update.vue) > - 页面缓存 keepAlive[RouteView.vue](src\layouts\RouteView.vue) 由于之前没有使用页面缓存,导致数据频繁刷新,目前加入了页面缓存,具体看[router.config.js](src\config\router.config.js)文件 > - 1、不使用 keep-alive 的情况:beforeRouteEnter --> created --> mounted --> destroyed > - 2、使用 keep-alive 的情况:beforeRouteEnter --> created --> mounted --> activated --> deactivated > - 3、使用 keep-alive,并且再次进入了缓存页面的情况:beforeRouteEnter -->activated --> deactivated > - table 高度自适应处理[utils](src\utils\index.js),实现逻辑,通过计算 table header 到页面顶部的高度,来动态当前 table 的高度,[STabel](src\components\Table\STable.js) 中给 table 赋予 scroll 参数 目前还存在问题,后期修复 对于超出宽度的表格,需要为表格 column 添加 width > - 商品多规格处处理 defaultSkuItemData 记得在这个对象中做参数的新增和修改 > - vue2 中如何使用组合式 API 和 vueuse 工具包[文章参考](https://www.cnblogs.com/Megasu/p/16217880.html) ## tailwindcss 配置参考 [官网](https://tailwindcss.com/docs/installation) [tailwindcss 在 Vue2 使用](https://blog.csdn.net/qq_40230735/article/details/123684730) ### tailwind.config.js 配置 ```js // tailwind.config.js module.exports = { purge: [], purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], darkMode: false, // or 'media' or 'class' theme: { extend: {}, }, variants: { extend: {}, }, plugins: [], corePlugins: { preflight: false, // 禁用默认样式,防止样式与默认样式产生冲突 }, } ``` ### postcss.config.js 配置 ```js module.exports = { plugins: { tailwindcss: {}, autoprefixer: {}, }, } ``` ## husky 配置 --- [-->husky 官网](https://www.npmjs.com/package/husky) ### husky Modern native Git hooks made easy Husky improves your commits and more 🐶 woof! ### Install ```cmd npm install husky --save-dev ``` Usage Edit package.json > prepare script and run it once: ```cmd npm set-script prepare "husky install" npm run prepare // 后面这两个一定要装,不然无效 npm install -D @commitlint/cli npm install -D @commitlint/config-conventional ``` ### 配置文件 [commitlint.config.js](./commitlint.config.js) ### Git 提交规范 参考 vue 规范 (Angular) - feat 增加新功能 - fix 修复问题/BUG - style 代码风格相关无影响运行结果的 - perf 优化/性能提升 - refactor 重构 - revert 撤销修改 - test 测试相关 - docs 文档/注释 - chore 依赖更新/脚手架配置修改等 - workflow 工作流改进 - ci 持续集成 - mod 不确定分类的修改 - wip 开发中 - types 类型修改 ### 如何关闭 在 .husky/commit-msg 内注释以下代码即可 ### npx --no-install commitlint --edit "$1" ### 示例 ```cmd git commit -m 'feat(home): add home page' ``` ## vue2.7 的 context getCurrentInstance 这里比较特殊,跟 vue3 有点区别,并且还需要对vue类型进行扩展 ```vue ``` ## ts改造 请求协助时的问题收集 - 用到ts开发的几个文件【后续新增的文件都是ts,不只下面的这几个文件】 [src\components\Icon](src\components\Icon) [src\hooks](src\hooks) [src\views\demo\Index.vue](src\views\demo\Index.vue) - vue 的setup中无法使用tsx语法【已决绝】 [src\views\demo\Index.vue](src\views\demo\Index.vue) - tsx文件中无法使用tsx语法【已决绝】 [src\views\demo\Index.vue 中引入 下面的文件](src\views\demo\Index.vue) [src\hooks\web\useMessage.tsx](src\hooks\web\useMessage.tsx) - vue 的setup中无法使用ts新语法【已决绝】 [src\views\demo\Index.vue](src\views\demo\Index.vue) - 配置别名没有生效,特别是 /@/和/#/ 导致这个原因是项目中有一个jsconfig.json 这个配置文件后面被我删除了,预计后期 vue.config.json都会被移除 ## 依赖升级指南 > 依赖升级只能一个一个的升级,不能全部一次性升级,这会导致颠覆性的错误,并且无法排除bug!执行以下命令即可看到目前有哪些依赖需要更新,并不是所有依赖都需要更新 ```dash npx taze ``` 1. lodash 替换为 lodash-es 只用一个依赖,记得修复 单独引入的内容,进行批量复制,之前项目中进行了分别单独引入,没必要 2. vue-router 升级3.x最高版本,并且记得在 [src\router\permission.js](src\router\permission.js) 进行修改;不升级vue-router4,原因在于当前项目很多都是optionsApi,而不是CompositionApi,并且也在vue-router^3.6做了封装,跟使用compositionApi差不多 3. viser-vue // Vue中使用Viser(基于AntV-G2可视化引擎) 这个没有用到,移除,不然vite打包报错 4. 优化 预防控制台警告[src\utils\propTypes.ts](src\utils\propTypes.ts) 如果不清楚来源,可到官网去参考[VueTypes.extend is deprecated. Use the ES6+ method instead.](https://dwightjack.github.io/vue-types/advanced/extending-vue-types.html#extending-namespaced-validators-in-es6) 5. [Migration to Vue 2.7](https://v2.cn.vuejs.org/v2/guide/migration-vue-2-7.html) vue-loader不需要装 6. 项目替换,只需要把views的所有文件copy到当前项目中即可,并做特殊的修改 ## 优化【参考vben-admin 2.8 不参考vben3的原因在于项目还未达到那样的标准】 1. iconify图标 雪碧图的优化,使用vite进行加载 就能获取本地assets/icons下的所有的svg雪碧图 2. hooks/core/setting/index.js 转为 ts 以及整个环境的优化 并引入新的依赖 3. [src\utils\utils.less](src\utils\utils.less) 样式优化,这里面的样式会影响到 tailwind的使用 4. 将tailwind 替换为 windicss 5. 打包配置参考 完成 > 由于本次的改动比较大,对于原来项目影响不到,主要在于加了很多新特性和移除冗余的依赖即更新依赖,方式旧依赖带来的深坑,特别是这个项目将来作为一个长期维护的项目必然要走的方向。优化后估计对项目的运行和性能会有所提升,开发体验跟vue3差不多,对于我们开发而言是比较好的过度和技术学习 ## 升级vite的过程中笔记 - [eslintrc.js](./.eslintrc.js) 这里做了太多的压制和移除很多限制,后期项目迁移完成在做放开,太多了 - 动态路由需要特殊优化 待定,后续确定迁移再做优化 - vite社区组件库[https://github.com/vitejs/awesome-vite寻插件v](https://github.com/vitejs/awesome-vite) - lazy_use 引入 需要在对应的问题添加 ```js // TODO 这一步需要引入,不然组件导入成功,样式导入会失败 import 'ant-design-vue/dist/antd.less' ``` - [打包报错 Unknown theme type: undefined, name: undefined 代码定位](node_modules\ant-design-vue\lib\icon\utils.js) 原因在于 使用antdv icon时 没有给到theme,导致打包报错 这个bug来源于 antdv内部的函数导致,当前我们在开发期间也要做好特殊处理,不然不好打包必然报错---最终需要处理的是 在 dist/index-xxx 将这段代码移除 throw new TypeError("Unknown theme type: "+C+", name: "+Ee) 【解决方案,在打包完成后写一个脚本去进行替换即可】[build\script\removeScript.ts](build\script\removeScript.ts) ```js // 这个函数是在antdv的内部函数,尽管项目中用到icon的地方都加了theme,但是还是会报错,可能是antdv内部组件自带的icon是没有 添加theme导致 function withThemeSuffix(type, theme = "outlined") { var result = type; if (theme === 'filled') { result += '-fill'; } else if (theme === 'outlined') { result += '-o'; } else if (theme === 'twoTone') { result += '-twotone'; } else { // TODO 这一行是有bug的 // (0, _warning2['default'])(false, 'Icon', 'This icon \'' + type + '\' has unknown theme \'' + theme + '\''); } return result; } ``` - 封装viteEnv和全局变量 - import.meta.env 不报红,需要在ts.config.json中配置type:["vite/client"] - 目前tsx无法直接使用注入的h,需要用h函数来加持,不然会报错 h is undefined,最有可能的原因是当前框架是vue2导致 暂时不去深究这个问题,后续如果升级到vue3,这个问题自然就能解决;那时估计这个项目也会重新做而不是以当前的框架来做 - [useMessage.ts](src\hooks\web\useMessage.tsx) 这个问题是个大问题,之前一直都是通过特殊的方式写,后面代码迁移过来之后,就是因为上面的一条bug,导致一些内容不能使用,只能换另一种方式处理 - 全局变量的配置 [.env](./.env) VITE_GLOB_APP_SHORT_NAME = saas_muilt_admin 这个字段最好使用英文,因为这个字段会被挂载到全局配置文件的window对象中 - 打包后运行报一下错误,经过排查,是配置文件没有被载入index.html文件中,感觉别人的项目为何构建得这么好是有原因的。只需要加入一个vite插件 [build\vite\plugin\html.ts](build\vite\plugin\html.ts),而且这个插件的加入需要做一个判断,只有是打包环境才需要加入,不然运行会报错 ```js // 这段代码是看了编译后的报错和编译后的代码发现的,然后引入后就能正常运行,很狗,如果是排查发现,还好发现的时间没有花费很长的时间,不然真不知道是个玩意的错 Cannot destructure property 'VITE_GLOB_APP_TITLE' of 'C' as it is undefined. at getAppEnvConfig ``` - [babel-preset-jsx](https://github.com/vuejs/jsx-vue2/tree/dev/packages/babel-preset-jsx#usage) 解决[issues](https://github.com/vuejs/composition-api/issues/943) 这个问题困扰了我快一个月啦 - vite antdv@1.7.8 日期控件报错TypeError: (void 0) is not a function ant-design-vue@1.7.8不在维护,基于现在vue2 + vite + antdv已存在问题 [解决方案](https://blog.csdn.net/qq_35459724/article/details/128684144) [插件 vite-plugin-antdv-fix](https://www.npmjs.com/package/vite-plugin-antdv-fix) - ant-design-vue 有 v1.7.3 升级到 v1.7.8 - v-bind="$attrs" 无法传递事件 [文章参考 vue3新特性](https://lhy308720327.gitee.io/2022/02/23/220223-Vue3-doc/) 需要添加 v-on="$listeners" $attrs 和 $listenner 的融合 我们知道,在vue2中我们使用v-bind=”$attrs”,v-on=”$listenner”来将数据和事件做一个承上启下的作用,但是在vue3中,首先是删除了v-on指令,其次是发现这两个组件的属性过于累赘,所以在当前版本中将 $attrs 和 $listenner 他们的功能进行了融合,$listenner 现在已作为 $attrs 的其中一部分进行传递,所以只需要在组建上指定 v-bind=”$attrs” ,那么将同时拥有传值和传递事件的功能。 - loading组件 指令触发待优化---有时间在处理 - tsx 写法注意事项 再迁移[BasicHelp](src/vbenComponents/Basic/src/BasicHelp.vue)组件的时候,发现报错 ```tsx function renderTitle() { const textList = props.text; if (isString(textList)) { return

{textList}

; } if (isArray(textList)) { // TODO 错误代码在于这一段 return textList.map((text, index) => { return (

<> {props.showIndex ? `${index + 1}. ` : ''} {text}

); }); // 修改后 return (textList as any).map((text, index) => { return (

{props.showIndex ? `${index + 1}. ` : ''} {text}

) }) } return null; } ``` - [modal.tsx组件](src/vbenComponents/Modal/src/components/Modal.tsx) 不能直接使用,因此使用了另外一种方式实现[VbenModal.vue](src/vbenComponents/Modal/src/components/VbenModal.vue) 这个过程中,需要移除 VbenModal 的ddraggable属性 ```tsx return () => { const propsData = { ...unref(attrs), ...props, onCancel } as Recordable // Todo 这中方式写并没有绑定 有bug 估计是antdv3 与 antdv1.7.8 导致的问题 // return {extendSlots(slots)}; return ( {extendSlots(slots)} ) } // Custom title component: get title const getMergeProps = computed((): Recordable => { return { // 移除 draggable 属性 ...omit(props, 'draggable'), ...(unref(propsRef) as any), } }) ``` - [modal模态组件](src/vbenComponents/Modal/src/hooks/useModal.ts) ```ts // 引入一个变量 来控制 watchEffect的的监听 不引入该变量的话,watchEffect无法监听 const dataChange = ref({}) watchEffect(() => { const data = dataTransfer[unref(uidRef)] if (!dataChange.value) return if (!data) return if (!callbackFn || !isFunction(callbackFn)) return nextTick(() => { callbackFn(data) }) }) ``` - [transition](src/vbenComponents/Transition/src/CreateTransition.tsx) 动画组件插槽渲染的bug ```tsx // 之前 return () => { const Tag = !props.group ? Transition : TransitionGroup; return ( {() => getSlot(slots)} ); }; // 处理后 () => getSlot(slots) 这种方式无法渲染 // vue 无法直接引入 这两个 组件Transition : TransitionGroup return () => { const TagName = !props.group ? 'transition' : 'transition-group' return ( {getSlot(slots)} ) } ``` - [usePage路由封装](src/hooks/web/usePage.ts) 解构后push 方法调用无效 ```ts // 这种方式结构无效,具体还不知道是是么原因 const { push, replace } = _router || useRouter(); // 优化后 const router = _router || useRouter() ``` - [useMessage](src\hooks\web\useMessage.tsx) 之间一直报错,解决方法如下 ```tsx // 之前写法 icon: getIcon(iconType) // 之后写法 icon: () => getIcon(iconType) ``` - [useI18n](src\hooks\web\useI18n.ts) 迁移过程中在使用的时候有一个主意事项需要特殊处理,如下 其次后期再App.vue页面发现,注入也存在问题,已经进行修复 还需要加入插件 vite-plugin-top-level-await 再进行动态加载语言的时候需要特殊处理 ```ts export function useI18n(namespace?: string): { t: I18nGlobalTranslation } { ... const tFn: I18nGlobalTranslation = (key: string, ...arg: any[]) => { if (!key) return '' if (!key.includes('.') && !namespace) return key // 下面是之前的写法,这种方法无法调用,我估计是 this的执行发生了改变导致的bug // return t(getKey(namespace, key), ...(arg as I18nTranslationRestParameters)) as any // 解决方案 return i18n.t(getKey(namespace, key), ...(arg as I18nTranslationRestParameters)) as any } ... } ``` - [moment 解决时间日期多语言bug](src/locales/useLocale.ts) [moment.js 中文国际化失效 vite vue2.7](https://blog.csdn.net/weixin_44495599/article/details/123701037) - antdv 打包样式报错,解决方案,注释掉[theme.ts](build/vite/plugin/theme.ts) antdDarkThemePlugin 这部分代码,并再main.ts引入 import('ant-design-vue/es/style') ant的样式,否则会导致打包错误,不能直接去掉theme.ts的一个原因是,自定义主题的btn样式需要再里面进行特殊排除 - [vue2.x的 h函数和vue3.x h函数有区别](https://www.jb51.net/article/270858.htm) 这对项目的改造有很大的意义 - [vditor 使用报错 Lute is not defined](https://ld246.com/article/1669649268191) 解决方案:需要将 vditor 包里的 dist/js/lute/lute.min.js 提前通过 cdn 的方式引入一下 > 框架更新进度 - [x] i18n多语言 - [ ] vuex -> pinia 已经安装后面再替换【待定】 - [ ] storage本地存储工具 -> Persist【待定】 - [ ] 动态路由优化 - [ ] 路由守卫优化 - [x] 权限 - [x] 指令 > 组件迁移进度 - [x] Button 无法继承antbutton - [ ] Application【待定】 - [x] Authority - [x] Basic - [x] Button - [ ] CardList - [x] ClickOutSide - [x] CodeEditor - [x] Container - [ ] ContextMenu - [x] CountDown - [x] CountTo - [x] Cropper - [x] Desctiption - [x] Drawer - [x] Dropdown - [x] Excel - [x] FlowChart - [x] Form【无法验证参数】 - [x] Icon - [ ] Loading - [x] Markdown - [ ] Menu【暂时不需要】 - [x] Modal - [x] Page - [ ] Preview - [x] Qrcode - [x] Scrollbar - [ ] SimpleMenu【暂时不需要】 - [x] StrengthMeter - [x] Table - [x] Time - [x] Tinymce - [x] Transition - [x] Tree - [ ] Upload - [x] Verify - [x] VirtualScroll - [ ] VxeTable