zl程序教程

您现在的位置是:首页 >  前端

当前栏目

浅析Vue项目如何基于Vuex进行qiankun微前端应用间通信方案实践:子应用无vuex共用主应用store的方案(子应用里如何保证主应用store在子应用的响应式)、子应用有独立store与主应用store分离共存的方案

Vue响应应用项目前端 如何 基于 实践
2023-09-11 14:19:54 时间

  主要探究下主应用和多个微应用之间如何使用Vuex来进行状态管理,这其实是对上一篇文章中通信方式第二种方式的补充,因为 vue 主要还是使用 vuex 作为状态管理。

一、场景选择

1、项目现状:

  1. 主应用是Vue技术栈,使用Vuex进行状态管理
  2. 多个微应用也是Vue技术栈,并且都可能使用Vuex进行状态管理

2、想要解决的问题:

  1. 主应用与微应用的通信
  2. 微应用之间的通信

3、通信方式的选择:

  1. qiankun 官方提供的通信方式 - Actions 通信  (不多说,看上篇文章即可);
  2. 使用shared实例通信,使用Vuex进行状态管理
  使用 vuex 进行状态管理的优点:
  • 子应用无法随意污染主应用的状态池,只能通过主应用暴露的 shared 实例的特定方法操作状态池,从而避免状态池污染产生的问题。
  • 子应用将具备独立运行的能力

二、核心思想

  主要就是在做微前端集成时,将主应用的store共享给所有微应用,针对不同微应用可以进行模块化设置,这样使得共享的state更加易于管理。

三、具体实现

(一)微应用原本就没有使用Vuex进行状态管理

1、主应用向微应用传递store实例

registerMicroApps([
          {
              name: "chai-project",
              entry: "//localhost:8080",
              container: '#yourContainer',
              activeRule: "/micro",
              props: {
                store //共享主应用的store实例
              }
          }
      ])

2、微应用使用主应用共享的store实例

  针对第一种情况,就是在入口文件中引入vuex,并使用该插件,进而在创建vue实例的时候,传入主应用共享的store实例。

import Vuex from 'vuex'
Vue.use(Vuex);
function render (props) {
  const store = props.store;
  // 在 render 中创建 VueRouter,可以保证在卸载微应用时,移除 location 事件监听,防止事件污染
  router = new Router({
    // 运行在主应用中时,添加路由命名空间 /micro
    base: window.__POWERED_BY_QIANKUN__ ? '/micro' : '/',
    mode: 'history',
    routes
  });

  // 挂载应用
  instance = new Vue({
    router,
    store,//主应用共享的store实例
    render: (h) => h(App)
  }).$mount('#app');
}

3、验证主应用和微应用之间是否可以完成通信,状态同步。

  验证的思路就是:在主应用和微应用的页面上添加改变同一个state的方法,并且利用computed实时显示该state的状态值。

  验证用例主要是:

  • 点击主应用按钮,修改state值之后,主应用和微应用的页面上都实时触发computed属性,展示最新状态值
  • 点击微应用按钮,修改state值之后,主应用和微应用的页面上都实时触发computed属性,展示最新状态值

  验证的结果:不论是点击主应用的按钮,还是点击微应用的按钮,主应用的computed属性成功被触发,微应用始终未能正常监听到状态值得改变,computed属性从未被触发。

4、bug修复:

  微应用的computed始终没有被触发,底层原因就是其依赖属性this.$store.state.count是非响应式的,这会导致难以触发。

  Vuex正常使用的时候,所有的状态值都是响应式的(需要主动在 state 里声明的才是响应式的),可以直接用于Vue页面之中,但是这里是非响应式的,导致这个的原因其实十分简单。

  这里的store实例是由主应用传递过来的,store中的状态对于主应用的Vue实例而言是亲儿子,是响应式的,在微应用中,虽然可以使用共享store实例中的commit方法,但是对于微应用的Vue实例而言,不是亲儿子,是非响应式的,这样分析之后,解决方案就十分明确:在微应用中将共享的store实例进行响应式设置,这是Vue现有的API方法Vue.observable(store)。

  如此处理之后,不论主应用还是微应用中,修改共享storestate状态值,在主应用和微应用中都能够实时感知,并对其做出响应的反馈。

(二)微应用本身就有自己store实例

  这种情况主要考虑的是两种方案:

  1. 主应用需要提前得知子应用的store内容,将其与主应用的store进行某种融合,这样子应用在集成环境中以及在独立运行时都能够正常运行。

    缺点:这方方案会导致主应用和子应用相互耦合过强,并且主应用和子应用都要维护一份子应用的store,增加工作量,过于笨重。

  2. 主应用依旧只传递主应用的store,子应用的store依旧在使用,也就是在子应用中既可以操作主应用的store,也可以操作子应用的store

    优点:主应用只需关注需要交互的状态即可,不用关心子应用原本的store内容。子应用也只需关注自己的store内容即可,降低耦合,减轻复杂度。

  我们主要考虑第 2 种方案的实现:父子应用store分离的方案实现

  这里基于父应用已经共享自己的store,并且主应用和子应用之间已经能够完成对于主应用的state状态变化的响应。

  考虑如何在子应用中使用两个storenew Vue()中目前注入的是主应用的store,那子应用本身的store如何全局注册呢?仔细思考后,其实很简单,只需要在入口文件中添加如下一行代码:

Vue.prototype.microStore = microStore;

  如此一来,在子应用的各个页面都能够通过this.microStore访问自身的store

computed: {
    microCount: {
        get (){
            return this.microStore.state.microCount;
        }
    }
}

主要来自于对下面这篇文章的学习,也是在查询微前端应用间通信方案时看到的,是对上一篇文章的补充。起初使用微前端时看的不是很能清晰理解,昨天自己在项目中实战主子应用间通信成功之后再回过头来看这篇文章,确实就清晰多了:《基于qiankun的微前端最佳实践-通信篇(Vuex)- https://www.jianshu.com/p/b2a77373c09e》