diff --git a/README.md b/README.md
index 41d7724..8f842de 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,7 @@
- [x] 基于DDD理念改造
- [x] 基于 vite-plugin-federation 拆分领域模块为联邦模块,实现微前端
+- [x] 基于Vue3+OOP+JSX改造项目代码,让项目更适合开发和维护
- [ ] 领域模块实现 docker 自动化构建部署上线
- [ ] Deno集成GraphQL
diff --git a/front-end/app-product/vite.config.ts b/front-end/app-product/vite.config.ts
index fa81816..d3f062a 100644
--- a/front-end/app-product/vite.config.ts
+++ b/front-end/app-product/vite.config.ts
@@ -22,9 +22,9 @@ export default defineConfig({
'./ProductRouter': './src/features/product/router/index.ts' // 商品路由
},
shared: {
- vue: {generate: false, requiredVersion: '^3.5.18'},
- 'vue-router': { generate:false, requiredVersion: '^4.0.6' },
- pinia: { generate:false, requiredVersion: '^3.0.3' }
+ vue: {import: false, generate: false, requiredVersion: '^3.5.18'},
+ 'vue-router': {import: false, generate: false, requiredVersion: '^4.0.6'},
+ pinia: {import: false, generate: false, requiredVersion: '^3.0.3'},
}
}),
vue(),
diff --git a/front-end/app-shared/vite.config.ts b/front-end/app-shared/vite.config.ts
index a3c0664..47f603b 100644
--- a/front-end/app-shared/vite.config.ts
+++ b/front-end/app-shared/vite.config.ts
@@ -17,7 +17,7 @@ export default defineConfig({
"./utils": "./src/utils/index.ts",
},
shared: {
- axios: {generate: false, requiredVersion: '^1.12.2'}
+ axios: {requiredVersion: '^1.12.2'}
}
})
],
diff --git a/front-end/main-app/package.json b/front-end/main-app/package.json
index bc5cc9f..e2eee58 100644
--- a/front-end/main-app/package.json
+++ b/front-end/main-app/package.json
@@ -1,5 +1,5 @@
{
- "name": "vue-project",
+ "name": "main-app",
"version": "0.0.0",
"private": true,
"type": "module",
@@ -19,16 +19,15 @@
"vue-router": "^4.0.6"
},
"devDependencies": {
+ "@abraham/reflection": "^0.13.0",
"@originjs/vite-plugin-federation": "^1.4.1",
- "@tsconfig/node22": "^22.0.2",
- "@types/node": "^22.16.5",
- "@vitejs/plugin-vue": "^6.0.1",
- "@vitejs/plugin-vue-jsx": "^5.0.1",
- "@vue/tsconfig": "^0.7.0",
- "npm-run-all2": "^8.0.4",
+ "@types/node": "^24.5.2",
+ "@vue3-oop/plugin-vue-jsx": "^1.5.1",
+ "injection-js": "^2.5.0",
+ "tslib": "^2.8.1",
"typescript": "~5.8.0",
"vite": "^7.0.6",
"vite-plugin-vue-devtools": "^8.0.0",
- "vue-tsc": "^3.0.4"
+ "vue3-oop": "^1.2.1"
}
}
diff --git a/front-end/main-app/src/app/App.tsx b/front-end/main-app/src/app/App.tsx
index e7661d1..20e7621 100644
--- a/front-end/main-app/src/app/App.tsx
+++ b/front-end/main-app/src/app/App.tsx
@@ -1,10 +1,10 @@
-import { defineComponent } from 'vue'
-import { RouterLink, RouterView } from "vue-router";
+import {Component, VueComponent} from 'vue3-oop'
+import {RouterLink, RouterView} from "vue-router";
-export default defineComponent({
- name: 'App',
- setup() {
- return () => (
+@Component()
+export class App extends VueComponent {
+ render() {
+ return (
<>
首页 |
@@ -15,4 +15,4 @@ export default defineComponent({
>
)
}
-})
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/front-end/main-app/src/app/components/Header.tsx b/front-end/main-app/src/app/components/Header.tsx
index 90e3bb2..2db39b2 100644
--- a/front-end/main-app/src/app/components/Header.tsx
+++ b/front-end/main-app/src/app/components/Header.tsx
@@ -1,59 +1,56 @@
-import { defineComponent, defineEmits, onMounted, PropType } from 'vue'
-import type { JSX } from "vue/jsx-runtime";
+import {Component, ComponentProps, Hook, useProps, VueComponent} from 'vue3-oop'
+import {JSX} from "vue/jsx-runtime";
+import {VNodeChild} from "vue";
-export default defineComponent({
- name: "Header",
- props: {
- text: {
- type: Array<{ id: number, title: string }>,
- default: () => []
- },
- // 点击事件
- onClick: {
- type: Function as PropType<() => void>,
- default: () => { }
- }
- },
- emits: {
- sendMessage: (message: string) => typeof message === 'string'
- },
+interface ListItemType {
+ id: number
+ title: string
+}
- setup(props, { attrs, slots, emit, expose }) {
+interface HeaderProps {
+ text?: string;
+ list: ListItemType[]
+ slots: {
+ default: () => JSX.Element;
+ haveName: () => JSX.Element;
+ item: (val: ListItemType) => VNodeChild;
+ }
+}
- onMounted(() => {
- console.log("onMounted")
- })
+@Component()
+export default class Header extends VueComponent
{
- const handleClick = () => {
- console.log("handleClick")
- emit('sendMessage', '子给父的数据')
- }
+ // required 的 true or false 需要和 类型中 text的? 对应
+ static defaultProps: ComponentProps = {
+ text: {default: '默认数值', required: true},
+ list: {default: () => []}
+ };
- const button = (): JSX.Element => {
- return
- }
+ @Hook('Mounted')
+ mounted() {
+ console.log("this: ", this);
+ console.log('Header 组件的 mounted 生命周期...')
+ }
- return () => (
-
-
头部组件-点我
- {button()}
+ render() {
+ const {text, list} = useProps
();
- {slots.default?.()}
-
- {slots.header?.()}
-
-
-
作用于插槽:
-
- {
- props.text.map(item => {
- return slots.scoped?.(item)
- })
- }
-
-
+ return (
+
)
}
-})
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/front-end/main-app/src/app/main.ts b/front-end/main-app/src/app/main.ts
index cd10a3b..95362a3 100644
--- a/front-end/main-app/src/app/main.ts
+++ b/front-end/main-app/src/app/main.ts
@@ -1,13 +1,21 @@
// import './assets/main.css'
-
-import { createApp } from 'vue'
-import { createPinia } from 'pinia'
-
-import App from './App'
+import '@abraham/reflection'
+import {createApp} from 'vue'
+import {createPinia} from 'pinia'
+import {App} from './App'
import router from './router'
-createApp(App)
- .use(createPinia())
- .use(router)
- .mount('#app')
+
+class Main {
+ constructor() {
+ createApp(App)
+ .use(createPinia())
+ .use(router)
+ .mount('#app')
+ }
+}
+
+
+new Main
+
diff --git a/front-end/main-app/src/app/router/Config.ts b/front-end/main-app/src/app/router/Config.ts
new file mode 100644
index 0000000..1a5dd26
--- /dev/null
+++ b/front-end/main-app/src/app/router/Config.ts
@@ -0,0 +1,25 @@
+import {productRouter} from 'product/ProductRouter'
+import {RouteRecordRaw} from 'vue-router'
+
+
+const baseRouter: Array = [
+ {
+ path: '/',
+ name: 'home',
+ component: () => import('../views/Home'),
+ },
+ {
+ path: '/about',
+ name: 'about',
+ component: () => import('../views/About'),
+ },
+ {
+ path: '/:pathMatch(.*)*',
+ name: 'NotFound',
+ component: () => import('../views/NotFound')
+ }
+];
+
+// 聚合所有功能模块的路由
+const routes: RouteRecordRaw[] = [...baseRouter, ...productRouter];
+export default routes;
\ No newline at end of file
diff --git a/front-end/main-app/src/app/router/index.ts b/front-end/main-app/src/app/router/index.ts
index 9282488..dddf15f 100644
--- a/front-end/main-app/src/app/router/index.ts
+++ b/front-end/main-app/src/app/router/index.ts
@@ -1,27 +1,5 @@
-import {createRouter, createWebHistory, RouteRecordRaw} from 'vue-router'
-import {productRouter} from 'product/ProductRouter'
-
-
-const baseRouter: Array = [
- {
- path: '/',
- name: 'home',
- component: () => import('../views/Home'),
- },
- {
- path: '/about',
- name: 'about',
- component: () => import('../views/About'),
- },
- {
- path: '/:pathMatch(.*)*',
- name: 'NotFound',
- component: () => import('../views/NotFound')
- }
-];
-
-// 聚合所有功能模块的路由
-const routes: RouteRecordRaw[] = [...baseRouter, ...productRouter];
+import {createRouter, createWebHistory} from 'vue-router'
+import routes from './Config'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
diff --git a/front-end/main-app/src/app/views/About.tsx b/front-end/main-app/src/app/views/About.tsx
index 11785ff..2ae82c5 100644
--- a/front-end/main-app/src/app/views/About.tsx
+++ b/front-end/main-app/src/app/views/About.tsx
@@ -1,12 +1,12 @@
-import { defineComponent } from 'vue'
+import {Component, VueComponent} from 'vue3-oop'
-export default defineComponent({
- name: "About",
- setup() {
- return () => (
-
-
我的
-
+@Component()
+export default class About extends VueComponent {
+ render() {
+ return (
+
+
我的
+
)
}
-})
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/front-end/main-app/src/app/views/Home.tsx b/front-end/main-app/src/app/views/Home.tsx
index bcdd665..608cc17 100644
--- a/front-end/main-app/src/app/views/Home.tsx
+++ b/front-end/main-app/src/app/views/Home.tsx
@@ -1,64 +1,54 @@
-import {defineComponent, onMounted, reactive} from 'vue'
+import {Autobind, Component, Link, Mut, VueComponent} from 'vue3-oop'
import Header from '@/components/Header'
-import {UrlCheckUtils} from 'shared/utils'
-import {useCounterStore} from '@/stores/counter'
-import {storeToRefs} from 'pinia'
-interface stateType {
- list: ListItemType[]
-}
interface ListItemType {
id: number
title: string
}
-export default defineComponent({
- name: "Home",
- setup() {
+@Component()
+export default class Home extends VueComponent {
- const counterStore = useCounterStore()
- const { increment } = counterStore
- const { count, doubleCount } = storeToRefs(counterStore)
+ @Mut()
+ count: number = 1
- const state = reactive({
- list: [
- { id: 1, title: '新闻1' },
- { id: 2, title: '新闻2' },
- { id: 3, title: '新闻3' },
- ]
- })
+ @Mut()
+ text: string = "Home props 传给 Header 的字符串"
+
+ @Mut()
+ newList: ListItemType[] = [
+ {id: 1, title: '新闻1'},
+ {id: 2, title: '新闻2'},
+ {id: 3, title: '新闻3'},
+ ]
+
+ @Link() H1?: HTMLDivElement
+ @Autobind()
+ async addCount() {
+ this.count++
+ this.text = "22222"
+ console.log(this.H1)
+ }
- onMounted(() => {
- // console.log("onMounted: ", HttpConfig.DevBaseUrl);
- console.log("check: ", UrlCheckUtils.check())
- })
+ render() {
+ return (
+
+
首页
+
count响应式变量(点我):{this.count}
+
父到子 default 插槽
,
+ haveName: () => 父到子 具名 插槽
,
+ item: (val) => {val.title}
+ }}
+ list={this.newList}
+ text={this.text}>
- // 定义处理子组件事件的函数
- const handleChildEvent = (message: string) => {
- console.log('收到子组件事件:', message)
- }
-
-
- return () => (
-
-
{
- console.log("通过props自定义事件传给子组件");
- }}
- onSendMessage={handleChildEvent}>
- {{
- scoped: (item: ListItemType) => {item.title},
- header: () => ,
- default: () => 父到子 default 插槽
- }}
-
-
首页
-
点我+1:{count.value}
-
+
+
)
}
-})
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/front-end/main-app/src/shared/types/ shims-tsx.d.ts b/front-end/main-app/src/shared/types/ shims-tsx.d.ts
new file mode 100644
index 0000000..f797d84
--- /dev/null
+++ b/front-end/main-app/src/shared/types/ shims-tsx.d.ts
@@ -0,0 +1,46 @@
+import Vue, {VNode} from 'vue'
+
+declare global {
+ namespace Vue {
+ any
+ }
+}
+
+declare global {
+ namespace JSX {
+ interface ElementAttributesProperty {
+ $props: any // 设置类组件的props类型检查属性
+ }
+
+ // tslint:disable no-empty-interface
+ interface Element extends VNode {
+ }
+
+ // tslint:disable no-empty-interface
+ interface ElementClass extends Vue {
+ }
+
+ interface IntrinsicAttributes {
+ // 给组件元素增加属性
+ on?: any
+ vModel?: any
+ vShow?: boolean
+ value?: any
+ oninput?: Function
+ nativeOnClick?: (event: MouseEvent) => void
+ oncontextmenu?: (event: MouseEvent) => void
+ onmouseup?: (event: MouseEvent) => void
+ onclick?: (event: MouseEvent) => void
+ onclick_prevent?: (event: MouseEvent) => void
+ ref?: string
+ key?: string | number
+ class?: string | string[]
+ slot?: string
+ style?: Partial | string | object | object[]
+ }
+
+ interface IntrinsicElements {
+ [elem: string]: any
+ }
+ }
+}
diff --git a/front-end/main-app/src/shared/types/shims-vue.d.ts b/front-end/main-app/src/shared/types/shims-vue.d.ts
new file mode 100644
index 0000000..6ad95a7
--- /dev/null
+++ b/front-end/main-app/src/shared/types/shims-vue.d.ts
@@ -0,0 +1,5 @@
+declare module '*.vue' {
+ import type {DefineComponent} from 'vue'
+ const component: DefineComponent<{}, {}, any>
+ export default component
+}
diff --git a/front-end/main-app/tsconfig.app.json b/front-end/main-app/tsconfig.app.json
deleted file mode 100644
index d1bd415..0000000
--- a/front-end/main-app/tsconfig.app.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "extends": "@vue/tsconfig/tsconfig.dom.json",
- "include": [
- "src/shared/types/*.d.ts",
- "src/**/*.ts",
- "src/**/*.d.ts",
- "src/**/*",
- "src/**/*.tsx",
- "src/**/*.vue"
- ],
- "exclude": [
- "src/**/__tests__/*"
- ],
- "compilerOptions": {
- "verbatimModuleSyntax": false,
- "jsx": "preserve",
- "jsxImportSource": "vue",
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
- "paths": {
- "@/*": [
- "./src/app/*"
- ],
- "@shared/*": [
- "./src/shared/*"
- ],
- "@features/*": [
- "./src/features/*"
- ],
- "@domains/*": [
- "./src/domains/*"
- ]
- }
- }
-}
\ No newline at end of file
diff --git a/front-end/main-app/tsconfig.json b/front-end/main-app/tsconfig.json
index 66b5e57..3c0207d 100644
--- a/front-end/main-app/tsconfig.json
+++ b/front-end/main-app/tsconfig.json
@@ -1,11 +1,46 @@
{
- "files": [],
- "references": [
- {
- "path": "./tsconfig.node.json"
- },
- {
- "path": "./tsconfig.app.json"
+ "compilerOptions": {
+ "target": "ESNext",
+ "module": "ESNext",
+ "importHelpers": true,
+ "isolatedModules": true,
+ "experimentalDecorators": true,
+ "emitDecoratorMetadata": true,
+ "useDefineForClassFields": false,
+ "moduleResolution": "Bundler",
+ "strict": true,
+ "jsx": "preserve",
+ "sourceMap": true,
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "lib": [
+ "ES2020",
+ "dom",
+ "dom.iterable",
+ "scripthost"
+ ],
+ "skipLibCheck": true,
+ "paths": {
+ "@/*": [
+ "./src/app/*"
+ ],
+ "@shared/*": [
+ "./src/shared/*"
+ ],
+ "@features/*": [
+ "./src/features/*"
+ ],
+ "@domains/*": [
+ "./src/domains/*"
+ ]
}
+ },
+ "include": [
+ "src/shared/types/*.d.ts",
+ "src/**/*.ts",
+ "src/**/*.d.ts",
+ "src/**/*",
+ "src/**/*.tsx",
+ "src/**/*.vue"
]
}
diff --git a/front-end/main-app/tsconfig.node.json b/front-end/main-app/tsconfig.node.json
deleted file mode 100644
index a83dfc9..0000000
--- a/front-end/main-app/tsconfig.node.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "extends": "@tsconfig/node22/tsconfig.json",
- "include": [
- "vite.config.*",
- "vitest.config.*",
- "cypress.config.*",
- "nightwatch.conf.*",
- "playwright.config.*",
- "eslint.config.*"
- ],
- "compilerOptions": {
- "noEmit": true,
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
-
- "module": "ESNext",
- "moduleResolution": "Bundler",
- "types": ["node"]
- }
-}
diff --git a/front-end/main-app/vite.config.ts b/front-end/main-app/vite.config.ts
index 043b24f..db2e855 100644
--- a/front-end/main-app/vite.config.ts
+++ b/front-end/main-app/vite.config.ts
@@ -1,12 +1,10 @@
import {fileURLToPath, URL} from 'node:url'
import {defineConfig} from 'vite'
-import vue from '@vitejs/plugin-vue'
-import vueJsx from '@vitejs/plugin-vue-jsx'
-import vueDevTools from 'vite-plugin-vue-devtools'
+import vueJsx from '@vue3-oop/plugin-vue-jsx'
+
import federation from '@originjs/vite-plugin-federation';
-// https://vite.dev/config/
export default defineConfig({
server: {
port: 1300,
@@ -14,9 +12,7 @@ export default defineConfig({
strictPort: true,
},
plugins: [
- vue(),
vueJsx(),
- vueDevTools(),
federation({
name: 'mainApp', // 主应用模块名(联邦模块需通过此名引用)
remotes: { // 配置远程联邦模块地址(开发/生产需对应)
@@ -25,7 +21,6 @@ export default defineConfig({
},
shared: {
vue: { requiredVersion: '^3.5.18' },
- axios: { requiredVersion: '^1.12.2' },
'vue-router': { requiredVersion: '^4.0.6' },
pinia: { requiredVersion: '^3.0.3' }
}
diff --git a/front-end/pnpm-workspace.yaml b/front-end/pnpm-workspace.yaml
new file mode 100644
index 0000000..be660d2
--- /dev/null
+++ b/front-end/pnpm-workspace.yaml
@@ -0,0 +1,4 @@
+packages:
+ - 'main-app'
+ - 'app-product'
+ - 'app-shared'
\ No newline at end of file