首页 > 解决方案 > 在 Vuejs 3 中实现插件系统

问题描述

我正在尝试为我的 Vue3/Laravel 应用程序实现一个(简单的)插件系统。为了快速获得工作版本,我决定定义一个全局变量 ( window.$plugins),它引用我的应用程序app和添加新插件的函数register(data)

插件需要一个主 js 文件main.js和一个应显示为插件的 vue 组件(例如Counter.vue)。(本文末尾是一个示例组件和插件)

服务器上的设置也很基本。如果服务器 ( ./plugins/Counter) 上存在文件夹,则该文件./plugins/Counter/counter.js将添加到我的主 HTML 并在应用程序本身之后加载。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- Styles -->
    <link href="css/app.css" rel="stylesheet">
</head>
<body>
    <div id="app" class="d-flex flex-column"></div>
    <!-- Scripts -->
    <script src="js/app.js"></script>
    <script src="js/file.js"></script>
</body>
</html>

当我现在加载我的应用程序时,插件也被加载了,但是有几个问题:

  1. 反应性不起作用。反应性变量发生变化(例如,如果我登录console.log(state.count)),但 HTML 部分未更新
  2. 模板中没有包含在自己的标签中的部分根本不显示
<template>
    <div>
        <!-- displayed; but stays at Count: 0 -->
        <span>Count: {{ state.count }}</span>
        <!-- not displayed -->
        Count: {{ state.count }}
        <!-- not displayed as well -->
        Hello Vue!
    </div>
</template>

有什么我想念的吗?我读了几篇文章,反应性的问题是import {reactive} from 'vue'我的插件中的 引用了另一个 vue 实例,而不是我的主应用程序中的导入。但我也读到这不是问题。我还尝试将reactive其作为全局window.$plugins变量的一部分公开。这解决了反应性问题,但 HTML 中未包装的行仍未呈现?

结果看起来应该可以正常工作,但是我缺少一部分来使它正确。因此,如果有人有提示或解决方案,我会非常高兴:)

主应用程序(使用 Laravel Mix 构建(Webpack)

// webpack.mix.js
mix.js('resources/js/app.js', 'public/js').vue();

// babel.config.js
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ]
}
// app.js
const app = createApp(App);
window.$plugins = {
    app: app,
    register: data => {
        // simple add plugin as global component
        window.$plugins.app.component(data.component.name, data.component);
    },
}
app.mount('#app');

插件(使用 vue-cli 构建)

// vue.config.js
module.exports = {
    productionSourceMap: false,
    chainWebpack: config => {
        config.optimization.delete('splitChunks')
    },
     filenameHashing: false,
}

// babel.config.js
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ]
}
// main.js
import Counter from './components/Counter.vue';

window.addEventListener('load', _ => {
    window.$plugins.register({
        // some data...
        component: Counter,
    });
});
<template>
    <div>
        Count: {{ state.count }}
        <button type="button" @click="inc()">Click</button>
    </div>
</template>

<script>
import {reactive} from 'vue';

export default {
    name: 'Counter',
    setup() {
        const state = reactive({
            count: 0,
        });
        const inc = _ => {
            state.count++;
        }

        return {
            state,
            inc,
        };
    }
}
</script>

标签: javascriptwebpackvuejs3vue-cli

解决方案


推荐阅读