umijs / qiankun

📦 🚀 Blazing fast, simple and complete solution for micro frontends.
https://qiankun.umijs.org
MIT License
15.84k stars 2.02k forks source link

路由属于子应用,多次点击后重复进入子应用 #2513

Open ada-hou opened 1 year ago

ada-hou commented 1 year ago

主应用版本:vue2 + qiankun2.10.8

主应用package.json

{
  "name": "qiankun_main",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^3.8.3",
    "qiankun": "^2.10.8",
    "vue": "^2.6.14",
    "vue-router": "^3.0.2"
  },
  "devDependencies": {
    "@babel/core": "^7.12.16",
    "@babel/eslint-parser": "^7.12.16",
    "@vue/cli-plugin-babel": "~5.0.0",
    "@vue/cli-plugin-eslint": "~5.0.0",
    "@vue/cli-service": "~5.0.0",
    "eslint": "^7.32.0",
    "eslint-plugin-vue": "^8.0.3",
    "vue-template-compiler": "^2.6.14"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "@babel/eslint-parser"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}

主应用main.js

import Vue from 'vue'
import App from './App.vue'
import {router} from "@/router";
import { registerMicroApps, start } from 'qiankun';

Vue.config.productionTip = false

new Vue({
    router,
  render: h => h(App),
}).$mount('#app')

registerMicroApps([
  // {
  //     name: "qiankunsubone", //子应用名称
  //     entry: "http://localhost:7101/", //子应用地址,假设此项目名称为智能质检应用(下面演示生命周期的时候会用到)
  //     container: "#subId", //子应用要挂载的节点,和vue.$mount("#app")类似;
  //     activeRule: ['#/subHome', '#/subAbout'] //重点:路由命中规则,当浏览器链接有#/quality时候,例如http://localhost:9000/#/quality/* ,就可以自动的把http://localhost:808挂载到本地的subapp-viewport节点下
  // },
  {
    name: "qiankunsubtwo", //子应用名称
    entry: " http://localhost:7105/", //子应用地址,假设此项目名称为智能质检应用(下面演示生命周期的时候会用到)
    container: "#subId", //子应用要挂载的节点,和vue.$mount("#app")类似;
    activeRule: ['#/sub2Home', '#/sub2About'] //重点:路由命中规则,当浏览器链接有#/quality时候,例如http://localhost:9000/#/quality/* ,就可以自动的把http://localhost:808挂载到本地的subapp-viewport节点下
  },
]);

start();

主应用router

import VueRouter from "vue-router";
import Vue from "vue";

Vue.use(VueRouter)
export const routes = [
    {path: '/', redirect: '/home'},
    // {
    //     path: '/qinakunLayout',
    //     name: 'qinakunLayout',
    //     component: () => import('@/components/qiankunLayout.vue'),
    //     children: [
    {
        path: '/home',
        name: 'Home',
        component: () => import('@/views/home/index.vue')
    },
    {
        path: '/sub2Home',
        name: 'sub2Home',
        component: () => import('@/views/sub/index.vue')
    },
    {
        path: '/sub2About',
        name: 'sub2About',
        component: () => import('@/views/sub/index.vue')
    }
    // ]
    // },
]
export const router = new VueRouter({
    base: '/',
    // mode: 'history',
    routes
})

sub2开头的两个路由是子应用路由,指到/views/sub/index.vue上


/views/sub/index.vue
<template>
    <div id="subId"><p>hahhshdhd</p></div>
</template>

<script>
    export default {
        name: 'sub-index'
    }
</script>

<style scoped>

</style>

主应用APP.VUE

<template>
  <div id="app">
    <button @click="clickRouteFn('/home')">首页</button>
    <button @click="clickRouteFn('/subHome')">第一个子应用</button>
    <button @click="clickRouteFn('/sub2Home')">第二个子应用</button>
    <button @click="clickRouteFn('/subOne')">第三个子应用</button>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App',
  methods: {
    clickRouteFn (path) {
      this.$router.push(
              {
                path
              }
      )
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

子应用版本Vue3 package.json

{
  "name": "vue3",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "start": "vue-cli-service serve",
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^3.0.0-0",
    "vue-router": "^4.0.0-beta.11",
    "vuex": "^4.0.0-beta.4"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0-0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^7.0.0-0",
    "less": "^3.0.4",
    "less-loader": "^5.0.0"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/vue3-essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}

router

const routes = [
  { path: '/sub2Home', name: 'home', component: () => import(/* webpackChunkName: "home" */ '@/views/Home') },
  { path: '/sub2About', name: 'about', component: () => import(/* webpackChunkName: "about" */ '@/views/About') },
];

export default routes;

main.js

import './public-path';
import { createApp } from 'vue';
import { createRouter, createWebHashHistory } from 'vue-router';
import App from './App.vue';
import routes from './router';
import store from './store';

let router = null;
let instance = null;
let history = null;

function render(props = {}) {
  const { container } = props;
  history = createWebHashHistory(window.__POWERED_BY_QIANKUN__ ? '/' : '/');
  router = createRouter({
    history,
    routes,
  });

  instance = createApp(App);
  instance.use(router);
  instance.use(store);
  instance.mount(container ? container.querySelector('#app') : '#app');
}

if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

export async function bootstrap() {
  console.log("vue3 bootstrap qiankun")
  // console.log('%c%s', 'color: green;', 'vue3.0 app bootstraped');
}

function storeTest(props) {
  props.onGlobalStateChange &&
    props.onGlobalStateChange(
      (value, prev) => console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev),
      true,
    );
  props.setGlobalState &&
    props.setGlobalState({
      ignore: props.name,
      user: {
        name: props.name,
      },
    });
}

export async function mount(props) {
  console.log("vue3 mount qiankun")
  storeTest(props);
  render(props);
  instance.config.globalProperties.$onGlobalStateChange = props.onGlobalStateChange;
  instance.config.globalProperties.$setGlobalState = props.setGlobalState;
}

export async function unmount() {
  console.log("vue3 退出 qiankun")
  instance.unmount();
  instance._container.innerHTML = '';
  instance = null;
  router = null;
  history.destroy();
}

运行后 image image 看起来的是没有问题的 当我这样点击时,首页-->第二个子应用-->About-->第二个子应用-->About 发现问题

image

当第二次点击子应用的about时,发生了如下事件: 1、进入子应用about组件 2、子应用卸载 3、退出子应用about组件 4、子应用加载 5、进入子应用about组件

当子应用是Vue2版本时,没有此问题

gongshun commented 1 year ago

同一个问题 https://github.com/umijs/qiankun/issues/1865

cjlhll commented 1 year ago

同一个问题 #1865

问题这个1865也没解决啊。