微前端(wujie)源码解析-3.wujie-vue

wujie-vue2源码解析

前言

在前面的文章中,我们对无界的使用方式和整体架构进行了分析,wujie-vue2、wujie-vue3、wujie-react作为无界架构中的重要一环,起到了桥梁的作用,对不同框架做了适配,今天我们就来分析一下wujie-vue2的源码,看看它是如何实现的

整体架构

当我们使用无界时,通常是这样使用的:

vue 复制代码
<WujieVue width="100%" height="100%" name="vue2" :url="'//localhost:7200/'" :sync="true"></WujieVue>

wujie-vue2的整体架构如下图所示:

wujie-vue2依赖wujie,并且以插件的形式暴露出一个组件,这样我们在开发的时候就可以使用这个组件了

目录结构

我们先来看下wujie-vue2的目录结构

lua 复制代码
├── package.json
├── webpack.config.js
├── index.js

还有一些其他的文件,这里就不一一列举了,我们主要看下index.js文件,这个文件是wujie-vue2的入口文件。

核心代码

我们首先看下wujie-vue2的入口文件index.js的输入输出

js 复制代码
import Vue from "vue";
import { bus, preloadApp, startApp as rawStartApp, destroyApp, setupApp } from "wujie";

const wujieVueOptions = {
 // code...
};

const WujieVue = Vue.extend(wujieVueOptions);

WujieVue.setupApp = setupApp;
WujieVue.preloadApp = preloadApp;
WujieVue.bus = bus;
WujieVue.destroyApp = destroyApp;
WujieVue.install = function (Vue) {
Vue.component("WujieVue", WujieVue);
};

export default WujieVue;

这段代码比较简单,我们来分析下:

  1. 首先我得依赖了vue以及wujie
  2. 定义了一个wujieVueOptions对象,这个对象是wujie-vue2的配置项,我们后面会详细分析
  3. 通过Vue.extend方法创建了一个WujieVue组件,这个组件就是我们在开发的时候使用的组件
  4. WujieVue组件上挂载了一些方法,包括注册组件、预加载、事件通信、销毁
  5. 最后挂载了一个install方法,这个方法我们比较熟悉,就是vue插件的安装方法,让后将WujieVue暴露出去

现在我们分析下wujie-vue2的配置项wujieVueOptions

js 复制代码
const wujieVueOptions = {
    name: "WujieVue",
    props: {
       width: { type: String, default: "" },
       height: { type: String, default: "" },
       name: { type: String, default: "" },
       loading: { type: HTMLElement, default: undefined },
       url: { type: String, default: "" },
       sync: { type: Boolean, default: undefined },
       prefix: { type: Object, default: undefined },
       alive: { type: Boolean, default: undefined },
       props: { type: Object, default: undefined },
       attrs: {type: Object, default: undefined},
       replace: { type: Function, default: undefined },
       fetch: { type: Function, default: undefined },
       fiber: { type: Boolean, default: undefined },
       degrade: { type: Boolean, default: undefined },
       plugins: { type: Array, default: null },
       beforeLoad: { type: Function, default: null },
       beforeMount: { type: Function, default: null },
       afterMount: { type: Function, default: null },
       beforeUnmount: { type: Function, default: null },
       afterUnmount: { type: Function, default: null },
       activated: { type: Function, default: null },
       deactivated: { type: Function, default: null },
       loadError: { type: Function, default: null },
    },
    data() {
       return {
          startAppQueue: Promise.resolve(),
       };
    },
    mounted() {
       bus.$onAll(this.handleEmit);
       this.execStartApp();
       this.$watch(
          () => this.name + this.url,
          () => this.execStartApp()
       );
    },
    methods: {
       handleEmit(event, ...args) {
          this.$emit(event, ...args);
       },
       async startApp() {
          try {
             // $props 是vue 2.2版本才有的属性,所以这里直接全部写一遍
             await rawStartApp({
                name: this.name,
                url: this.url,
                el: this.$refs.wujie,
                loading: this.loading,
                alive: this.alive,
                fetch: this.fetch,
                props: this.props,
                attrs: this.attrs,
                replace: this.replace,
                sync: this.sync,
                prefix: this.prefix,
                fiber: this.fiber,
                degrade: this.degrade,
                plugins: this.plugins,
                beforeLoad: this.beforeLoad,
                beforeMount: this.beforeMount,
                afterMount: this.afterMount,
                beforeUnmount: this.beforeUnmount,
                afterUnmount: this.afterUnmount,
                activated: this.activated,
                deactivated: this.deactivated,
                loadError: this.loadError,
             });
          } catch (error) {
             console.log(error);
          }
       },
       execStartApp() {
          this.startAppQueue = this.startAppQueue.then(this.startApp);
       },
       destroy() {
          destroyApp(this.name);
       },
    },
    beforeDestroy() {
       bus.$offAll(this.handleEmit);
    },
    render(c) {
       return c("div", {
          style: {
             width: this.width,
             height: this.height,
          },
          ref: "wujie",
       });
    },
};

整体上看,这个配置项就是一个vue组件的配置项,我们在开发的时候,可以通过这些配置项来配置我们的组件

我们还是以上文提到的例子为入手点,从组件实际使用时的生命周期的角度来分析下:

  1. 当我们使用该组件的时候,props会传入一些参数,例如:width、height、name、url等等,这几个参数都比较好理解,width、height是组件的宽高,name是组件的名称,url是组件的地址
  2. render函数会渲染一个div,这个div的宽高就是我们传入的width和height,这个div的ref是wujie
  3. 当组件挂载到页面上的时候,会执行mounted钩子函数,这个钩子函数中,做了三件事情:
    1. 监听了bus的所有事件,当bus触发事件的时候,会执行handleEmit方法,这个方法会将bus的事件转化为vue的事件,然后触发vue的事件
    2. 执行了execStartApp方法,这个方法会执行startApp方法,继而会执行rawStartApp方法,这个方法是重点,我们以后会分析,这个函数最终会渲染一个子应用
    3. 添加watch监听了nameurl的变化,当nameurl发生变化的时候,会重新执行execStartApp方法,完成组件的重新渲染
  4. 当组件销毁的时候,会执行beforeDestroy钩子函数,钩子函数会移除bus的所有事件监听

总结

wujie-vue2的源码简单清晰,主要是对wujie的封装,最终暴露出一个我们大家都认识的组件,我们在开发的时候,只需要像正常使用一个组件一样使用它就可以了,非常方便。在wujie-vue3,wujie-react中,也是类似的封装逻辑,大家有兴趣可以自行了解。

下期预告:我们将开始分析wujie-core的源码,敬请期待。

今天的分享就到这里,感谢大家的阅读,如果大家喜欢我的文章,可以给个star,你们的支持是我写作的最大动力,谢谢大家!

相关推荐
想吃火锅10052 小时前
【leetcode】405.数字转换为十六进制数js
开发语言·javascript·ecmascript
原则猫4 小时前
HOOKS 背后机制
前端
码语智行4 小时前
首页导航跳转功能深度解析-系统内和系统外
前端
阿猫的故乡5 小时前
Vue过渡动画从入门到装X:淡入淡出、滑动、列表动画、第三方库全搞定
前端·javascript·vue.js
IManiy5 小时前
总结之Vibe Coding前端骨架
前端
小和尚敲木头5 小时前
vue3 vite动态拼接图片路径
javascript
JS菌5 小时前
AI Agent 沙箱双层防护体系:从权限过滤到内核隔离的完整实现
前端·人工智能·后端
Aphasia3115 小时前
从输入URL到页面展示全流程
前端·面试
我叫黑大帅6 小时前
前端如何竖屏固定视口背景
前端·javascript·面试
abcy0712136 小时前
python pandas csv异步后台清洗前端优先返回成功信息
前端·python·pandas