Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 微前端 #2

Merged
merged 2 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/shell-vue-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
"preview": "vite preview"
},
"dependencies": {
"element-plus": "^2.7.7",
"vue": "^3.4.29",
"vue-router": "^4.4.0",
"wujie-vue3": "^1.0.22"
},
"devDependencies": {
Expand Down
132 changes: 1 addition & 131 deletions apps/shell-vue-app/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,139 +1,9 @@
<script setup lang="ts">
import { onBeforeUnmount, reactive } from 'vue'
import WujieVue from 'wujie-vue3'

const { bus } = WujieVue
const apps = reactive([
{
name: 'vue3',
url: '//localhost:8001/',
visible: true,
},
{
name: 'vue2',
url: '//localhost:8002/',
visible: false,
},
])

function createContext() {
const windowMap = new Map()

function setWindow(win: Window) {
windowMap.set(win.name, win)
}

return reactive({
setWindow,
router: {
push(name: string, path: string) {
const win = windowMap.get(name)
if (win.$router) {
win.$router.push(path)
showApp(name)
}
},
},
})
}

const ctx = createContext()

function showApp(name: string) {
apps.forEach((x) => {
x.visible = x.name === name
})
}

function beforeLoad() {

}

function beforeMount(win: Window) {
ctx.setWindow(win)
console.log(win)
}

function afterMount(_win: Window) {

}

function beforeUnmount() {

}

function afterUnmount() {

}

const { router } = ctx

const tabs = reactive<{ app: string, path: string }[]>([])

function addTab(app: string, path: string) {
const x = tabs.find((x) => {
return x.app === app && x.path === path
})
if (!x) {
tabs.push({
app,
path,
})
}
}
bus.$on('addTab', addTab)
onBeforeUnmount(() => {
bus.$off('addTab', addTab)
})
</script>

<template>
<div class="flex">
<div class="w-72 border-r flex flex-col min-h-screen">
<button @click="showApp('vue3')">
显示 Vue3 项目
</button>
<button @click="showApp('vue2')">
显示 Vue2 项目
</button>
<button @click="router.push('vue3', '/')">
切换到 Vue3 /
</button>
<button @click="router.push('vue3', '/foo')">
切换到 Vue3 /foo
</button>
<button @click="router.push('vue3', '/bar')">
切换到 Vue3 /bar
</button>
<button @click="router.push('vue2', '/')">
切换到 Vue2 /
</button>
<button @click="router.push('vue2', '/foo')">
切换到 Vue2 /foo
</button>
<button @click="router.push('vue2', '/bar')">
切换到 Vue2 /bar
</button>
</div>
<div class="grow">
<div class="border-b p-4 space-x-2">
<div
v-for="tab in tabs" :key="tab.path" class="border rounded-lg inline-block p-1 cursor-pointer hover:bg-sky-700"
@click="router.push(tab.app, tab.path)"
>
{{ tab.app }} {{ tab.path }}
</div>
</div>
<div>
<WujieVue
v-for="app in apps" v-show="app.visible" :key="app.name" width="100%" height="100%" :name="app.name"
:url="app.url" :sync="true" :beforeLoad="beforeLoad" :beforeMount="beforeMount" :afterMount="afterMount"
:beforeUnmount="beforeUnmount" :afterUnmount="afterUnmount"
:alive="true"
/>
</div>
</div>
</div>
<router-view />
</template>

<style scoped></style>
87 changes: 87 additions & 0 deletions apps/shell-vue-app/src/layout/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<script lang="ts" setup>
import { onBeforeUnmount, reactive } from "vue";
import { useRoute, useRouter } from "vue-router";
import WujieVue from "wujie-vue3";

const { bus } = WujieVue;
const apps = reactive([
{
name: "vue3",
path: "/vue3",
url: "//localhost:8001/",
visible: true,
children: [
{
name: "foo",
path: "/vue3-sub/foo",
url: "//localhost:8001/foo",
},
{
name: "bar",
path: "/vue3-sub/bar",
url: "//localhost:8001/bar",
},
],
},
{
name: "vue2",
path: "/vue2",
url: "//localhost:8002/",
visible: false,
children: [
{
name: "foo",
path: "/vue2-sub/foo",
url: "//localhost:8002/foo",
},
{
name: "bar",
path: "/vue2-sub/bar",
url: "//localhost:8002/bar",
},
],
},
]);

const currentRoute = useRoute();

const $router = useRouter();
</script>

<template>
<div>
<div class="fixed top-0 bottom-0 left-0 z-50 w-52">
<el-scrollbar>
<el-menu
default-active="vue3"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

background-color="bg-slate-700"
text-color="bg-white"
active-text-color="bg-blue-400"
:unique-opened="false"
:collapse-transition="false"
mode="vertical"
>
<el-sub-menu v-for="item in apps" :key="item.name" :index="item.name">
<template #title>
<span>{{ item.name }}</span>
</template>
<router-link
v-for="ele in item.children"
:key="item.name + ele.name"
:to="ele.path"
>
<el-menu-item :index="item.name + '-' + ele.path">
<span class="text-white">{{ ele.name }}</span>
</el-menu-item>
</router-link>
</el-sub-menu>
</el-menu>
</el-scrollbar>
</div>
<section
class="relative h-full min-h-screen ml-52 overflow-y-auto bg-white"
>
<router-view />
</section>
</div>
</template>
24 changes: 22 additions & 2 deletions apps/shell-vue-app/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,27 @@ import { createApp } from 'vue'
import './style.css'
import WujieVue from 'wujie-vue3'
import App from './App.vue'
import router from './router/index.ts'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const { bus, setupApp, preloadApp, destroyApp } = WujieVue
const app = createApp(App)

createApp(App).use(WujieVue).mount('#app')
const { bus } = WujieVue;

bus.$on("sub-route-change", (name: string, path: string) => {
const mainName = `${name}-sub`;
const mainPath = `/${name}-sub${path}`;
const currentName = router.currentRoute.value.name;
const currentPath = router.currentRoute.value.path;
console.log(555555555555, name, path, mainName, mainPath, currentName, currentPath)
if (mainName === currentName && mainPath !== currentPath) {
router.push({ path: mainPath });
}
});

app.use(WujieVue)
app.use(ElementPlus)
app.use(router)

app.mount('#app')
50 changes: 50 additions & 0 deletions apps/shell-vue-app/src/pages/common/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<template>
<WujieVue
width="100%"
height="100%"
:name="props.name"
:url="url"
:alive="props.alive"
:beforeLoad="beforeLoad"
:beforeMount="beforeMount"
:afterMount="afterMount"
:beforeUnmount="beforeUnmount"
:afterUnmount="afterUnmount"
></WujieVue>
</template>

<script setup lang="ts">
import { defineProps, computed, watch } from "vue";
import { useRoute } from "vue-router";
import wujieVue from "wujie-vue3";

const route = useRoute();

const props = defineProps({
url: String,
name: String,
alive: Boolean,
});

const url = computed(() => {
return props.url + (`${route.params.path ? route.params.path : ""}`);
});

watch(() => route.params.path, (newPath) => {
wujieVue.bus.$emit(`${props.name}-router-change`, newPath ? newPath : '');
}, { immediate: true });

function beforeLoad() {}

function beforeMount() {

}

function afterMount(_win: Window) {}

function beforeUnmount() {}

function afterUnmount() {}
</script>

<style lang="scss" scoped></style>
73 changes: 73 additions & 0 deletions apps/shell-vue-app/src/router/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { createRouter, createWebHistory } from "vue-router";

const Layout = () => import("../layout/index.vue");
const Common = () => import("../pages/common/index.vue");

// 静态路由
export const constantRoutes: any[] = [
{
path: "/",
redirect: "/vue3-sub/index",
},

{
path: "/",
name: "/",
component: Layout,
children: [
{
path: "/vue3",
name: "Vue3",
component: Common,
props: {
url: "//localhost:8001/",
alive: true,
name: "vue3"
},
key: "vue3"
},
{
path: "/vue2",
name: "Vue2",
component: Common,
props: {
url: "//localhost:8002/",
alive: true,
name: "vue2"
},
key: "vue2"
},
{
path: "/vue3-sub/:path",
name: "vue3-sub",
component: Common,
props: {
url: "//localhost:8001/",
alive: true,
name: "vue3"
},
key: "vue3"
},
{
path: "/vue2-sub/:path",
name: "vue2-sub",
component: Common,
props: {
url: "//localhost:8002/",
alive: true,
name: "vue2"
},
key: "vue2"
}
],
},
];

const router = createRouter({
history: createWebHistory(),
routes: constantRoutes,
// 刷新时,滚动条位置还原
scrollBehavior: () => ({ left: 0, top: 0 }),
});

export default router;
Loading