微前端/Web 组件/Vue 路由器错误:未捕获的类型错误:无法重新定义属性:$router [英] Micro Front End / Web Components / Vue Router Error : Uncaught TypeError: Cannot redefine property: $router

查看:33
本文介绍了微前端/Web 组件/Vue 路由器错误:未捕获的类型错误:无法重新定义属性:$router的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个问题,下面是场景:

我开发了一个 vue 应用程序(my-admin 微应用程序),它有 4 - 5 个屏幕/组件(管理用户、管理通知、管理角色等),我创建了一个 路由器.js 我在其中写了以下内容:

...导入...Vue.use(VueRouter);//}const 路由 = [{小路: '/',name: '主布局',组件:主布局,孩子们:[{路径:'管理用户',name : '管理用户',组件:管理用户组件},{路径:'管理角色',name : '管理角色',组件:ManageRoleComponent}]}]const 路由器 = 新的 VueRouter({路线})导出默认路由器

并且我在我的 ma​​in.js 中导入了这个路由器对象,如下所示:

...导入...新的 Vue({路由器,渲染:h =>h(应用程序),}).$mount('#app')

最后我将我的这个微型应用程序包装为 main.js 中的 Web 组件(MainLayout 组件),如下所示:

const myAdmin = wrap(Vue,MainLayout)window.customElements.define('my-admin', myAdmin)

构建这个微型应用程序,使用以下命令:

"build": "vue-cli-service build --target wc --name my-admin ./src/main.js",

这就是这个微型应用程序的全部内容.如果我单独运行这个微型应用程序,它就会完美运行.

但在我的场景中,我有一个仅在 Vue 中开发的 shell 应用程序 (my-shell).并且这个 shell 应用程序也有它的自己的 vue 路由器并导入到它的 main.js 中,如下所示:

.外壳路由器:

...导入...Vue.use(VueRouter);const 路由 = [{小路: '/',name: '容器',组件:容器,孩子们:[{路径:'管理员',名称:'管理员微应用',组件:AdminMicroAppContainerComponent},{路径:'其他',名称:'其他微应用',组件:OtherMicroAppContainerComponent}]}]const 路由器 = 新的 VueRouter({路线})导出默认路由器

并且我将此路由器对象导入到 my-shell 的 main.js 中,如下所示:

new Vue({路由器,店铺,渲染:h =>h(应用程序)}).$mount('#app')

在 my-shell 的 index.html 中,我添加了标签(在里面)以加载我的微应用程序构建(my-admin.js 文件),如下所示:

 <script src="../assets/my-admin/dist/my-admin.js"></script><script src="../assets/other-microapps/dist/micro-app.js"></script>

但是当我启动 my-shell 应用程序时.它抛出以下错误:

未捕获的类型错误:无法重新定义属性:$router.

我该怎么做才能消除这个错误?

解决方案

我没有尝试重新创建这个场景,但是我可以发现它不起作用的明显原因.

让我们简要了解一下启动 SPA 时会发生什么.

路由器在开始时初始化,即 new Vue() 并且您的子应用程序附加在中间,即在 Dom Rerender 上,按照此顺序,您不能从中间应用程序返回到顶部而不破坏任何东西,要么丢弃初始路由器,要么拒绝新路由器.

我的建议:

<块引用>

不要在你的子应用(网络组件)中使用 vue-router,使用轻量级代码来处理路由.

根据我做微前端架构的经验,整个目标是尽可能地坚持 SOLID 模式.如果您的子应用程序复杂到需要 vue-router 进行路由,那么您就做错了*.

通常,子应用应该只做一件事.

例如在商业 SaaS 软件中,客户微应用仅负责

  1. 创建新客户(弹出模式)
  2. 列出客户
  3. 查看单个客户的交易报告
  4. 编辑客户信息(弹出模式)

处理客户付款、债务和复杂的图表报告均由另一个子应用程序处理.

只有 2 和 3 需要路由,我们使用 v-if 语句处理.

I have stucked with a issue, Below is the scenario :

I have developed a vue application (my-admin micro app) which has 4 - 5 screens/components (manage user , manage notifications ,manage roles etc) and i created a router.js where i have wrote following :

...imports... 
Vue.use(VueRouter);
// }
const routes = [
  {
    path: '/',
    name: 'main-layout',
    component: MainLayout,
    children:[
      {
        path : 'manage-user',
        name : 'manage-user',
        component : ManageUserComponent
      },
      {
        path : 'manage-role',
        name : 'manage-role',
        component : ManageRoleComponent
      }
    ]
  }
]

const router = new VueRouter({
  routes
})

export default router

and i imported this router object in my main.js like below :

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

and at last i wrap my this micro app as web component (MainLayout component) in main.js as below :

const myAdmin = wrap(Vue,MainLayout)

window.customElements.define('my-admin', myAdmin)

i build this micro app with following command :

"build": "vue-cli-service build --target wc --name my-admin ./src/main.js",

thats all for this micro app . and it is running perfectly if i run this micro app individually.

But in my scenario , i have a shell application (my-shell) which is developed in Vue only. and this shell application also has its own vue router and imported in its main.js like below :

. shell router :

...imports... 

Vue.use(VueRouter);

const routes = [
  {
    path: '/',
    name: 'container',
    component: Container,
    children:[
      {
        path : 'admin',
        name : 'admin-microapp',
        component : AdminMicroAppContainerComponent
      },
      {
        path : 'other',
        name : 'other-microapp',
        component : OtherMicroAppContainerComponent
      }
    ]
 }
]

const router = new VueRouter({
  routes
})

export default router

and i imported this router object in to my-shell's main.js like below :

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

and inside my-shell's index.html i added tags (inside )to load my micro apps buid (my-admin.js file) like below :

 <script src="../assets/my-admin/dist/my-admin.js"></script>
 <script src="../assets/other-microapps/dist/micro-app.js"></script>

But when i am starting my-shell application . it is throwing below error :

Uncaught TypeError: Cannot redefine property: $router. 

What can I do to get rid of this error?

解决方案

I've not tried recreatting this scenario, however I can spot the obvious reason why it doesn't work.

Lets briefly look at what happens when you launch an SPA.

Router's are initialize at the beginning, i.e new Vue() and your sub-apps are attached midway i.e on the Dom Rerender, following this sequence, you can't jump from mid-app back to the top without breaking things either the initial router is discarded or the new one is rejected.

My advice:

Don't use vue-router in your subapps (web components), use a lightweight code to handle routing.

In my experience doing micro-frontend architecture, the whole goal is to stick to the SOLID pattern as much as possible. If your sub-apps are complex to the extent that they require vue-router for routing, then you're not doing it right*.

Typically, a sub-app should be such that does only one thing.

e.g In a business SaaS software for example, A customer micro app is only responsible for

  1. Creating new customer (pop up modal)
  2. Listing Customers
  3. Viewing a single customer's transaction report
  4. Editing customer informattion (pop up modal)

Handling customer payments, debts and complex charting reports is each handled by another sub-app.

Only 2 and 3 require routing and we handled that with v-if statements.

这篇关于微前端/Web 组件/Vue 路由器错误:未捕获的类型错误:无法重新定义属性:$router的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆